The following small test case causes GCC to ICE: struct A; struct B { B(A const &); explicit B(B const &); }; struct A { A(B) {} }; B f(A const &a) { return B(a); } Same result (ICE) on the following two systems: gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) gcc (GCC) 4.1.1 20070105 (Red Hat 4.1.1-51) If the "explicit" keyword is dropped the ICE disappears. The same is true if the argument to A's constructor is changed to an reference.
Just tested it on the latest release 4.2.2 build from source with no patches and the ICE is still there. System: g++ (GCC) 4.2.2 Linux localhost.localdomain 2.6.20-1.2952.fc6 #1 SMP Wed May 16 18:59:18 EDT 2007 i686 i686 i386 GNU/Linux Fedora Core release 6 (Zod)
Confirmed. Even if it doesn't look like it makes sense to have an explicit copy constructor, the standard does not seem to prohibit this. But, B f(A const &a) { return B(a); } invokes the copy constructor for B, and thus would raise an error. A diagnostic is missing. Interestingly EDG ICEs as well ;) /icpc -strict_ansi -S t.C icpc: error: Fatal error in /suse/rguenther/bin/opt/intel/cce/9.1.039/bin/mcpcom, terminated by segmentation violation compilation aborted for t.C (code 1) 2.95 wrongly accepts this code, but doesn't ICE. So not a regression IMHO.
(In reply to comment #2) > 2.95 wrongly accepts this code, but doesn't ICE. So not a regression > IMHO. No it is a regression as anything (besides another ICE) to ICE is considered a regression. I remember we put these rules somewhere.
Related testcase: struct A; struct B { B (A const &); B (B &); }; struct A { A (B) {} }; B f (A const &a) { return B (a); } which doesn't have explicit at all segfaults as well, also endless recursion. In both cases the copy constructor can't be used, so a conversion through A(B) constructor and then B(const A&) is attempted. But that needs a temporary, so a B(const B &) copy constructor is needed and we are back to the original problem. If A's constructor is instead A (const B &) {}, then it compiles just fine in both variants ( explicit B (const B &); and B (B &); ). So I guess we just need to detect recursion here. I believe C++ will try only one hop through some other class' constructor, so perhaps just remembering one parent type would be enough to prevent the recursion.
Related to PR28475, then?
Yes, probably even a dup of that. I don't have 2.95 to verify this is a regression.
*** Bug 28475 has been marked as a duplicate of this bug. ***
As long as we're digging back... the test case in Comment #4 also ICEs: gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) also "works": gcc version 2.95.3 [FreeBSD] 20010315 (release)
Subject: Bug 34824 Author: jason Date: Wed Feb 13 04:06:03 2008 New Revision: 132282 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=132282 Log: PR c++/34824 * call.c (convert_like_real): Pass LOOKUP_ONLYCONVERTING to build_temp if we're doing conversions to call a user-defined conversion function. Added: trunk/gcc/testsuite/g++.dg/overload/copy1.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c
Fixed for 4.3.0. Bugs on invalid code don't seem worth backporting.
Adjust target milestone.