This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/34824 (infinite mutual recursion on copy-initialization)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 12 Feb 2008 23:05:25 -0500
- Subject: C++ PATCH for c++/34824 (infinite mutual recursion on copy-initialization)
The problem here was that the special handing of copy-initialization led
us to allow us to indefinitely add more user-defined conversions in
order to try to satisfy the desired constructor call. Fixed by using
user_conv_p to inform recursive calls to convert_like_real that we are
in the context of a user-defined conversion, and therefore to disallow
any additional UDCs.
Tested x86_64-pc-linux-gnu, applied to trunk.
2008-02-12 Jason Merrill <jason@redhat.com>
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.
Index: cp/call.c
===================================================================
*** cp/call.c (revision 132281)
--- cp/call.c (working copy)
*************** convert_like_real (conversion *convs, tr
*** 4319,4324 ****
--- 4319,4325 ----
{
tree totype = convs->type;
diagnostic_fn_t diagnostic_fn;
+ int flags;
if (convs->bad_p
&& convs->kind != ck_user
*************** convert_like_real (conversion *convs, tr
*** 4357,4362 ****
--- 4358,4369 ----
{
struct z_candidate *cand = convs->cand;
tree convfn = cand->fn;
+ unsigned i;
+
+ /* Set user_conv_p on the argument conversions, so rvalue/base
+ handling knows not to allow any more UDCs. */
+ for (i = 0; i < cand->num_convs; ++i)
+ cand->convs[i]->user_conv_p = true;
expr = build_over_call (cand, LOOKUP_NORMAL);
*************** convert_like_real (conversion *convs, tr
*** 4454,4461 ****
/* Copy-initialization where the cv-unqualified version of the source
type is the same class as, or a derived class of, the class of the
destination [is treated as direct-initialization]. [dcl.init] */
! expr = build_temp (expr, totype, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
! &diagnostic_fn);
if (diagnostic_fn && fn)
diagnostic_fn (" initializing argument %P of %qD", argnum, fn);
return build_cplus_new (totype, expr);
--- 4461,4472 ----
/* Copy-initialization where the cv-unqualified version of the source
type is the same class as, or a derived class of, the class of the
destination [is treated as direct-initialization]. [dcl.init] */
! flags = LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING;
! if (convs->user_conv_p)
! /* This conversion is being done in the context of a user-defined
! conversion, so don't allow any more. */
! flags |= LOOKUP_NO_CONVERSION;
! expr = build_temp (expr, totype, flags, &diagnostic_fn);
if (diagnostic_fn && fn)
diagnostic_fn (" initializing argument %P of %qD", argnum, fn);
return build_cplus_new (totype, expr);
Index: testsuite/g++.dg/overload/copy1.C
===================================================================
*** testsuite/g++.dg/overload/copy1.C (revision 0)
--- testsuite/g++.dg/overload/copy1.C (revision 0)
***************
*** 0 ****
--- 1,20 ----
+ // PR c++/34824
+
+ struct A;
+
+ struct B
+ {
+ B (A const &); // { dg-warning "note" }
+ B (B &); // { dg-warning "note" }
+ };
+
+ struct A
+ {
+ A (B);
+ };
+
+ B
+ f (B const& b)
+ {
+ return b; // { dg-error "" }
+ }