This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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 "" }
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]