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).