Summary: | [10/11/12 Regression] explicit constructor is used in copy-initialization | ||
---|---|---|---|
Product: | gcc | Reporter: | Fedor Chelnokov <fchelnokov> |
Component: | c++ | Assignee: | Marek Polacek <mpolacek> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | mpolacek, webrown.cpp |
Priority: | P2 | Keywords: | accepts-invalid |
Version: | 12.2.1 | ||
Target Milestone: | 10.5 | ||
See Also: | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109663 | ||
Host: | Target: | ||
Build: | Known to work: | 4.4.7, 5.1.0, 7.1.0, 8.1.0, 8.5.0 | |
Known to fail: | 10.1.0, 9.1.0 | Last reconfirmed: | 2023-03-16 00:00:00 |
Description
Fedor Chelnokov
2023-03-16 19:51:48 UTC
Reduced testcase without the constraint that GCC accepts: struct A { A( float ) {} template<class U> explicit A( U ) {} }; void f(A t) { t = {1}; } Oy, started with r9-3735-gb5ff4f5c0d61e5: commit b5ff4f5c0d61e52e27a0727ae9e011aab525ccfd Author: Marek Polacek <polacek@redhat.com> Date: Tue Oct 30 19:59:41 2018 +0000 Implement P0892R2, explicit(bool). This hunk broke it: @@ -3251,6 +3251,12 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, goto fail; } + /* Now the explicit specifier might have been deduced; check if this + declaration is explicit. If it is and we're ignoring non-converting + constructors, don't add this function to the set of candidates. */ + if ((flags & LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (fn)) + return NULL; It doesn't check for BRACE_ENCLOSED_INITIALIZER_P (or some similar flag meaning we're initializing from an initializer_list) and that's the bug. The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:a226590fefb35ed66adf73d85cefe49048a78ab8 commit r13-6765-ga226590fefb35ed66adf73d85cefe49048a78ab8 Author: Marek Polacek <polacek@redhat.com> Date: Fri Mar 17 18:25:13 2023 -0400 c++: explicit ctor and list-initialization [PR109159] When I implemented explicit(bool) in r9-3735, I added this code to add_template_candidate_real: + /* Now the explicit specifier might have been deduced; check if this + declaration is explicit. If it is and we're ignoring non-converting + constructors, don't add this function to the set of candidates. */ + if ((flags & LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (fn)) + return NULL; but as this test demonstrates, that's incorrect when we're initializing from a {}: for list-initialization we consider explicit constructors and complain if one is chosen. PR c++/109159 gcc/cp/ChangeLog: * call.cc (add_template_candidate_real): Add explicit decls to the set of candidates when the initializer is a braced-init-list. libstdc++-v3/ChangeLog: * testsuite/20_util/pair/cons/explicit_construct.cc: Adjust dg-error. * testsuite/20_util/tuple/cons/explicit_construct.cc: Likewise. * testsuite/23_containers/span/explicit.cc: Likewise. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/explicit16.C: New test. Fixed on trunk so far. The patch caused non-bug bug 109247, so I don't think it's appropriate to backport this (?). |