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

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