public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/101460] New: Useless cascade of overload resolution errors for invalid expression
@ 2021-07-15 11:11 redi at gcc dot gnu.org
  2021-07-15 11:58 ` [Bug c++/101460] " redi at gcc dot gnu.org
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2021-07-15 11:11 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 101460
           Summary: Useless cascade of overload resolution errors for
                    invalid expression
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Keywords: diagnostic
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

template<bool> struct enable_if { };
template<> struct enable_if<true> { using type = void; };

template<bool B>
using enable_if_t = typename enable_if<B>::type;

struct tuple { };
struct pair { };

template<unsigned N> enable_if_t<N == 1> get(tuple&) { }
template<unsigned N> enable_if_t<N == 1> get(const tuple&) { }
template<unsigned N> enable_if_t<N == 1> get(pair&) { }
template<unsigned N> enable_if_t<N == 1> get(const pair&) { }

template<int N>
constexpr unsigned
frob()
{
  static_assert(N == 1, "user-friendly diagnostic");
  return unsigned{N}; // narrowing check, reject negative values
}

template<int N> void get_n(tuple& t) { get<frob<N>()>(t); }

int main()
{
  tuple t;
  get_n<-1>(t);
}

This prints a wall of errors:

stupid.C: In instantiation of 'constexpr unsigned int frob() [with int N =
-1]':
stupid.C:23:51:   required from 'void get_n(tuple&) [with int N = -1]'
stupid.C:28:12:   required from here
stupid.C:19:19: error: static assertion failed: user-friendly diagnostic
   19 |   static_assert(N == 1, "user-friendly diagnostic");
      |                 ~~^~~~
stupid.C:19:19: note: '(-1 == 1)' evaluates to false
stupid.C:20:20: error: narrowing conversion of '-1' from 'int' to 'unsigned
int' [-Wnarrowing]
   20 |   return unsigned{N}; // narrowing check, reject negative values
      |                    ^
stupid.C:21:1: error: body of 'constexpr' function 'constexpr unsigned int
frob() [with int N = -1]' not a return-statement
   21 | }
      | ^
stupid.C: In instantiation of 'void get_n(tuple&) [with int N = -1]':
stupid.C:28:12:   required from here
stupid.C:23:54: error: no matching function for call to
'get<frob<-1>()>(tuple&)'
   23 | template<int N> void get_n(tuple& t) { get<frob<N>()>(t); }
      |                                        ~~~~~~~~~~~~~~^~~
stupid.C:10:42: note: candidate: 'template<unsigned int N> enable_if_t<(N ==
1)> get(tuple&)'
   10 | template<unsigned N> enable_if_t<N == 1> get(tuple&) { }
      |                                          ^~~
stupid.C:10:42: note:   template argument deduction/substitution failed:
stupid.C:23:51: error: 'constexpr unsigned int frob() [with int N = -1]' called
in a constant expression
   23 | template<int N> void get_n(tuple& t) { get<frob<N>()>(t); }
      |                                            ~~~~~~~^~
stupid.C:17:1: note: 'constexpr unsigned int frob() [with int N = -1]' is not
usable as a 'constexpr' function because:
   17 | frob()
      | ^~~~
stupid.C:23:51: note: in template argument for type 'unsigned int'
   23 | template<int N> void get_n(tuple& t) { get<frob<N>()>(t); }
      |                                            ~~~~~~~^~
stupid.C:11:42: note: candidate: 'template<unsigned int N> enable_if_t<(N ==
1)> get(const tuple&)'
   11 | template<unsigned N> enable_if_t<N == 1> get(const tuple&) { }
      |                                          ^~~
stupid.C:11:42: note:   template argument deduction/substitution failed:
stupid.C:23:51: error: 'constexpr unsigned int frob() [with int N = -1]' called
in a constant expression
   23 | template<int N> void get_n(tuple& t) { get<frob<N>()>(t); }
      |                                            ~~~~~~~^~
stupid.C:23:51: note: in template argument for type 'unsigned int'
stupid.C:12:42: note: candidate: 'template<unsigned int N> enable_if_t<(N ==
1)> get(pair&)'
   12 | template<unsigned N> enable_if_t<N == 1> get(pair&) { }
      |                                          ^~~
stupid.C:12:42: note:   template argument deduction/substitution failed:
stupid.C:23:51: error: 'constexpr unsigned int frob() [with int N = -1]' called
in a constant expression
   23 | template<int N> void get_n(tuple& t) { get<frob<N>()>(t); }
      |                                            ~~~~~~~^~
stupid.C:23:51: note: in template argument for type 'unsigned int'
stupid.C:13:42: note: candidate: 'template<unsigned int N> enable_if_t<(N ==
1)> get(const pair&)'
   13 | template<unsigned N> enable_if_t<N == 1> get(const pair&) { }
      |                                          ^~~
stupid.C:13:42: note:   substitution of deduced template arguments resulted in
errors seen above


This is reduced from libstdc++ where there are more overloads of get<N> and all
of them get tried, and all of them print exactly the same error.

Why are we even attempting overload resolution when the expression is invalid?
Is the invalid non-constant frob<-1>() call going to suddenly become valid if
we keep trying hard enough?

If PR 96286 gets fixed then the static_assert in frob should stop compilation,
but if we remove that from the code above then we'll still get a wall of
unhelpful errors. Constant evaluation of frob<-1>() failed, so stop trying to
use it as a template argument.

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

* [Bug c++/101460] Useless cascade of overload resolution errors for invalid expression
  2021-07-15 11:11 [Bug c++/101460] New: Useless cascade of overload resolution errors for invalid expression redi at gcc dot gnu.org
@ 2021-07-15 11:58 ` redi at gcc dot gnu.org
  2021-07-15 12:04 ` redi at gcc dot gnu.org
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2021-07-15 11:58 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2021-07-15
     Ever confirmed|0                           |1

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I suppose the problem here is that the failed constant evaluation of frob<-1>()
only happens as a result of trying to use it as a template argument (where a
constant expression is required) which doesn't happen until overload resolution
is performed. So we have to at least being doing OR before we get a problem.

But maybe we can remember that it failed once, and so stop trying. If it's not
a valid constant expression, *that* is the error, not the fact that none of the
get<N> overloads can be called with an invalid constant expression.

Even if I change the code to do this it keeps trying overload resolution for
get<n>:

template<int N> void get_n(tuple& t) {
  constexpr unsigned n = frob<N>();
  get<n>(t);
}

The constexpr initialization of 'n' failed with a static_assert *and* a
non-constant narrowing conversion, so why do we continue and even attempt
overload resolution for 'get'?

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

* [Bug c++/101460] Useless cascade of overload resolution errors for invalid expression
  2021-07-15 11:11 [Bug c++/101460] New: Useless cascade of overload resolution errors for invalid expression redi at gcc dot gnu.org
  2021-07-15 11:58 ` [Bug c++/101460] " redi at gcc dot gnu.org
@ 2021-07-15 12:04 ` redi at gcc dot gnu.org
  2021-07-15 15:26 ` cvs-commit at gcc dot gnu.org
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2021-07-15 12:04 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I know that attempting to continue compiling can be very useful, so that
additional errors in the code can still be diagnosed. But in this case, maybe
we should mark 'n' as "tainted" so that we don't keep showing diagnostics
caused by trying to use it as if it was valid.

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

* [Bug c++/101460] Useless cascade of overload resolution errors for invalid expression
  2021-07-15 11:11 [Bug c++/101460] New: Useless cascade of overload resolution errors for invalid expression redi at gcc dot gnu.org
  2021-07-15 11:58 ` [Bug c++/101460] " redi at gcc dot gnu.org
  2021-07-15 12:04 ` redi at gcc dot gnu.org
@ 2021-07-15 15:26 ` cvs-commit at gcc dot gnu.org
  2021-07-19 12:38 ` cvs-commit at gcc dot gnu.org
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2021-07-15 15:26 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:17855eed7fc76b2cee7fbbc26f84d3c8b99be13c

commit r12-2327-g17855eed7fc76b2cee7fbbc26f84d3c8b99be13c
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Jul 14 20:14:14 2021 +0100

    libstdc++: Fix std::get<T> for std::tuple [PR101427]

    The std::get<T> functions relied on deduction failing if more than one
    base class existed for the type T.  However the implementation of Core
    DR 2303 (in r11-4693) made deduction succeed (and select the
    more-derived base class).

    This rewrites the implementation of std::get<T> to explicitly check for
    more than one occurrence of T in the tuple elements, making it
    ill-formed again. Additionally, the large wall of overload resolution
    errors described in PR c++/101460 is avoided by making std::get<T> use
    __get_helper<I> directly instead of calling std::get<I>, and by adding a
    deleted overload of __get_helper<N> for out-of-range N.

    Signed-off-by: Jonathan Wakely <jwakely@redhat.com>

    libstdc++-v3/ChangeLog:

            PR libstdc++/101427
            * include/std/tuple (tuple_element): Improve static_assert text.
            (__get_helper): Add deleted overload.
            (get<i>(tuple<T...>&&), get<i>(const tuple<T...>&&)): Use
            __get_helper directly.
            (__get_helper2): Remove.
            (__find_uniq_type_in_pack): New constexpr helper function.
            (get<T>): Use __find_uniq_type_in_pack and __get_helper instead
            of __get_helper2.
            * testsuite/20_util/tuple/element_access/get_neg.cc: Adjust
            expected errors.
            * testsuite/20_util/tuple/element_access/101427.cc: New test.

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

* [Bug c++/101460] Useless cascade of overload resolution errors for invalid expression
  2021-07-15 11:11 [Bug c++/101460] New: Useless cascade of overload resolution errors for invalid expression redi at gcc dot gnu.org
                   ` (2 preceding siblings ...)
  2021-07-15 15:26 ` cvs-commit at gcc dot gnu.org
@ 2021-07-19 12:38 ` cvs-commit at gcc dot gnu.org
  2021-08-30 13:45 ` jason at gcc dot gnu.org
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2021-07-19 12:38 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-11 branch has been updated by Jonathan Wakely
<redi@gcc.gnu.org>:

https://gcc.gnu.org/g:6dc150d9a036cbbed3c4dac6df1ce895b899d423

commit r11-8777-g6dc150d9a036cbbed3c4dac6df1ce895b899d423
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Jul 14 20:14:14 2021 +0100

    libstdc++: Fix std::get<T> for std::tuple [PR101427]

    The std::get<T> functions relied on deduction failing if more than one
    base class existed for the type T.  However the implementation of Core
    DR 2303 (in r11-4693) made deduction succeed (and select the
    more-derived base class).

    This rewrites the implementation of std::get<T> to explicitly check for
    more than one occurrence of T in the tuple elements, making it
    ill-formed again. Additionally, the large wall of overload resolution
    errors described in PR c++/101460 is avoided by making std::get<T> use
    __get_helper<I> directly instead of calling std::get<I>, and by adding a
    deleted overload of __get_helper<N> for out-of-range N.

    Signed-off-by: Jonathan Wakely <jwakely@redhat.com>

    libstdc++-v3/ChangeLog:

            PR libstdc++/101427
            * include/std/tuple (tuple_element): Improve static_assert text.
            (__get_helper): Add deleted overload.
            (get<i>(tuple<T...>&&), get<i>(const tuple<T...>&&)): Use
            __get_helper directly.
            (__get_helper2): Remove.
            (__find_uniq_type_in_pack): New constexpr helper function.
            (get<T>): Use __find_uniq_type_in_pack and __get_helper instead
            of __get_helper2.
            * testsuite/20_util/tuple/element_access/get_neg.cc: Adjust
            expected errors.
            * testsuite/20_util/tuple/element_access/101427.cc: New test.

    (cherry picked from commit 17855eed7fc76b2cee7fbbc26f84d3c8b99be13c)

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

* [Bug c++/101460] Useless cascade of overload resolution errors for invalid expression
  2021-07-15 11:11 [Bug c++/101460] New: Useless cascade of overload resolution errors for invalid expression redi at gcc dot gnu.org
                   ` (3 preceding siblings ...)
  2021-07-19 12:38 ` cvs-commit at gcc dot gnu.org
@ 2021-08-30 13:45 ` jason at gcc dot gnu.org
  2021-08-30 21:23 ` cvs-commit at gcc dot gnu.org
  2021-08-30 21:29 ` jason at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: jason at gcc dot gnu.org @ 2021-08-30 13:45 UTC (permalink / raw)
  To: gcc-bugs

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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Assignee|unassigned at gcc dot gnu.org      |jason at gcc dot gnu.org
                 CC|                            |jason at gcc dot gnu.org
             Status|NEW                         |ASSIGNED

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

* [Bug c++/101460] Useless cascade of overload resolution errors for invalid expression
  2021-07-15 11:11 [Bug c++/101460] New: Useless cascade of overload resolution errors for invalid expression redi at gcc dot gnu.org
                   ` (4 preceding siblings ...)
  2021-08-30 13:45 ` jason at gcc dot gnu.org
@ 2021-08-30 21:23 ` cvs-commit at gcc dot gnu.org
  2021-08-30 21:29 ` jason at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2021-08-30 21:23 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:a8de832470f78a40a0e2c8de866a471bf74bf0ab

commit r12-3234-ga8de832470f78a40a0e2c8de866a471bf74bf0ab
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Aug 30 09:44:28 2021 -0400

    c++: fold function template args sooner [PR101460]

    As discussed in the PR, we were giving a lot of unnecessary errors for this
    testcase because we didn't try to do constant evaluation until
    convert_nontype_argument, which happens for each of the candidates.  But
    when looking at a template-id as the function operand of a call, we can try
    to fold arguments before we get into overload resolution.

            PR c++/101460

    gcc/cp/ChangeLog:

            * cp-tree.h (cxx_constant_value_sfinae): Declare.
            * constexpr.c (cxx_constant_value_sfinae): New.
            * pt.c (fold_targs_r, maybe_fold_fn_template_args): New.
            (tsubst_copy_and_build) [CALL_EXPR]: Call
            maybe_fold_fn_template_args.

    gcc/testsuite/ChangeLog:

            * g++.dg/template/explicit-args6.C: New test.

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

* [Bug c++/101460] Useless cascade of overload resolution errors for invalid expression
  2021-07-15 11:11 [Bug c++/101460] New: Useless cascade of overload resolution errors for invalid expression redi at gcc dot gnu.org
                   ` (5 preceding siblings ...)
  2021-08-30 21:23 ` cvs-commit at gcc dot gnu.org
@ 2021-08-30 21:29 ` jason at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: jason at gcc dot gnu.org @ 2021-08-30 21:29 UTC (permalink / raw)
  To: gcc-bugs

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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |12.0
         Resolution|---                         |FIXED
             Status|ASSIGNED                    |RESOLVED

--- Comment #6 from Jason Merrill <jason at gcc dot gnu.org> ---
Fixed for GCC 12.

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

end of thread, other threads:[~2021-08-30 21:29 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-15 11:11 [Bug c++/101460] New: Useless cascade of overload resolution errors for invalid expression redi at gcc dot gnu.org
2021-07-15 11:58 ` [Bug c++/101460] " redi at gcc dot gnu.org
2021-07-15 12:04 ` redi at gcc dot gnu.org
2021-07-15 15:26 ` cvs-commit at gcc dot gnu.org
2021-07-19 12:38 ` cvs-commit at gcc dot gnu.org
2021-08-30 13:45 ` jason at gcc dot gnu.org
2021-08-30 21:23 ` cvs-commit at gcc dot gnu.org
2021-08-30 21:29 ` jason 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).