From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id C9D82397B827; Thu, 15 Jul 2021 11:11:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C9D82397B827 From: "redi at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/101460] New: Useless cascade of overload resolution errors for invalid expression Date: Thu, 15 Jul 2021 11:11:18 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 12.0 X-Bugzilla-Keywords: diagnostic X-Bugzilla-Severity: normal X-Bugzilla-Who: redi at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status keywords bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 15 Jul 2021 11:11:18 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D101460 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 struct enable_if { }; template<> struct enable_if { using type =3D void; }; template using enable_if_t =3D typename enable_if::type; struct tuple { }; struct pair { }; template enable_if_t get(tuple&) { } template enable_if_t get(const tuple&) { } template enable_if_t get(pair&) { } template enable_if_t get(const pair&) { } template constexpr unsigned frob() { static_assert(N =3D=3D 1, "user-friendly diagnostic"); return unsigned{N}; // narrowing check, reject negative values } template void get_n(tuple& t) { get()>(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 =3D -1]': stupid.C:23:51: required from 'void get_n(tuple&) [with int N =3D -1]' stupid.C:28:12: required from here stupid.C:19:19: error: static assertion failed: user-friendly diagnostic 19 | static_assert(N =3D=3D 1, "user-friendly diagnostic"); | ~~^~~~ stupid.C:19:19: note: '(-1 =3D=3D 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 =3D -1]' not a return-statement 21 | } | ^ stupid.C: In instantiation of 'void get_n(tuple&) [with int N =3D -1]': stupid.C:28:12: required from here stupid.C:23:54: error: no matching function for call to 'get()>(tuple&)' 23 | template void get_n(tuple& t) { get()>(t); } | ~~~~~~~~~~~~~~^~~ stupid.C:10:42: note: candidate: 'template enable_if_t<(N = =3D=3D 1)> get(tuple&)' 10 | template enable_if_t get(tuple&) { } | ^~~ stupid.C:10:42: note: template argument deduction/substitution failed: stupid.C:23:51: error: 'constexpr unsigned int frob() [with int N =3D -1]' = called in a constant expression 23 | template void get_n(tuple& t) { get()>(t); } | ~~~~~~~^~ stupid.C:17:1: note: 'constexpr unsigned int frob() [with int N =3D -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 void get_n(tuple& t) { get()>(t); } | ~~~~~~~^~ stupid.C:11:42: note: candidate: 'template enable_if_t<(N = =3D=3D 1)> get(const tuple&)' 11 | template enable_if_t 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 =3D -1]' = called in a constant expression 23 | template void get_n(tuple& t) { get()>(t); } | ~~~~~~~^~ stupid.C:23:51: note: in template argument for type 'unsigned int' stupid.C:12:42: note: candidate: 'template enable_if_t<(N = =3D=3D 1)> get(pair&)' 12 | template enable_if_t get(pair&) { } | ^~~ stupid.C:12:42: note: template argument deduction/substitution failed: stupid.C:23:51: error: 'constexpr unsigned int frob() [with int N =3D -1]' = called in a constant expression 23 | template void get_n(tuple& t) { get()>(t); } | ~~~~~~~^~ stupid.C:23:51: note: in template argument for type 'unsigned int' stupid.C:13:42: note: candidate: 'template enable_if_t<(N = =3D=3D 1)> get(const pair&)' 13 | template enable_if_t 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 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 inval= id? 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 compilati= on, 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.=