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]

[C++ PATCH] Fix bug 2608, a regression


Hi,
I've installed this patch on both mainline and branch as it fixes
a 2.95 regression.

Unfortunately, we use clones directly in overload resolution. This means
that constructor default args introduced in the definition must be
propagated to the clones.

built & tested on i686-pc-linux-gnu, approved by Mark.

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-04-27  Nathan Sidwell  <nathan@codesourcery.com>

	* cp-tree.h (adjust_clone_args): Prototype new function.
	* class.c (adjust_clone_args): New function.
	* decl.c (start_function): Call it for in charge ctors.

Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.375
diff -c -3 -p -r1.375 class.c
*** class.c	2001/04/20 15:29:09	1.375
--- class.c	2001/04/27 10:20:48
*************** clone_function_decl (fn, update_method_v
*** 4407,4412 ****
--- 4407,4486 ----
    DECL_ABSTRACT (fn) = 1;
  }
  
+ /* DECL is an in charge constructor, which is being defined. This will
+    have had an in class declaration, from whence clones were
+    declared. An out-of-class definition can specify additional default
+    arguments. As it is the clones that are involved in overload
+    resolution, we must propagate the information from the DECL to its
+    clones. */
+ 
+ void
+ adjust_clone_args (decl)
+      tree decl;
+ {
+   tree clone;
+   
+   for (clone = TREE_CHAIN (decl); clone && DECL_CLONED_FUNCTION (clone);
+        clone = TREE_CHAIN (clone))
+     {
+       tree orig_clone_parms = TYPE_ARG_TYPES (TREE_TYPE (clone));
+       tree orig_decl_parms = TYPE_ARG_TYPES (TREE_TYPE (decl));
+       tree decl_parms, clone_parms;
+ 
+       clone_parms = orig_clone_parms;
+       
+       /* Skip the 'this' parameter. */
+       orig_clone_parms = TREE_CHAIN (orig_clone_parms);
+       orig_decl_parms = TREE_CHAIN (orig_decl_parms);
+ 
+       if (DECL_HAS_IN_CHARGE_PARM_P (decl))
+ 	orig_decl_parms = TREE_CHAIN (orig_decl_parms);
+       if (DECL_HAS_VTT_PARM_P (decl))
+ 	orig_decl_parms = TREE_CHAIN (orig_decl_parms);
+       
+       clone_parms = orig_clone_parms;
+       if (DECL_HAS_VTT_PARM_P (clone))
+ 	clone_parms = TREE_CHAIN (clone_parms);
+       
+       for (decl_parms = orig_decl_parms; decl_parms;
+ 	   decl_parms = TREE_CHAIN (decl_parms),
+ 	     clone_parms = TREE_CHAIN (clone_parms))
+ 	{
+ 	  my_friendly_assert (same_type_p (TREE_TYPE (decl_parms),
+ 					   TREE_TYPE (clone_parms)), 20010424);
+ 	  
+ 	  if (TREE_PURPOSE (decl_parms) && !TREE_PURPOSE (clone_parms))
+ 	    {
+ 	      /* A default parameter has been added. Adjust the
+ 		 clone's parameters. */
+ 	      tree exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
+ 	      tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
+ 	      tree type;
+ 
+ 	      clone_parms = orig_decl_parms;
+ 
+ 	      if (DECL_HAS_VTT_PARM_P (clone))
+ 		{
+ 		  clone_parms = tree_cons (TREE_PURPOSE (orig_clone_parms),
+ 					   TREE_VALUE (orig_clone_parms),
+ 					   clone_parms);
+ 		  TREE_TYPE (clone_parms) = TREE_TYPE (orig_clone_parms);
+ 		}
+ 	      type = build_cplus_method_type (basetype,
+ 					      TREE_TYPE (TREE_TYPE (clone)),
+ 					      clone_parms);
+ 	      if (exceptions)
+ 		type = build_exception_variant (type, exceptions);
+ 	      TREE_TYPE (clone) = type;
+ 	      
+ 	      clone_parms = NULL_TREE;
+ 	      break;
+ 	    }
+ 	}
+       my_friendly_assert (!clone_parms, 20010424);
+     }
+ }
+ 
  /* For each of the constructors and destructors in T, create an
     in-charge and not-in-charge variant.  */
  
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.604
diff -c -3 -p -r1.604 cp-tree.h
*** cp-tree.h	2001/04/26 20:05:33	1.604
--- cp-tree.h	2001/04/27 10:20:53
*************** extern tree build_expr_type_conversion		
*** 3759,3764 ****
--- 3759,3765 ----
  extern tree type_promotes_to			PARAMS ((tree));
  extern tree perform_qualification_conversions   PARAMS ((tree, tree));
  extern void clone_function_decl                 PARAMS ((tree, int));
+ extern void adjust_clone_args			PARAMS ((tree));
  
  /* decl.c */
  /* resume_binding_level */
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.776
diff -c -3 -p -r1.776 decl.c
*** decl.c	2001/04/25 08:31:17	1.776
--- decl.c	2001/04/27 10:21:05
*************** start_function (declspecs, declarator, a
*** 13345,13350 ****
--- 13345,13356 ----
  	}
      }
  
+   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
+     /* This is a constructor, we must ensure that any default args
+        introduced by this definition are propagated to the clones
+        now. The clones are used directly in overload resolution.  */
+     adjust_clone_args (decl1);
+ 
    /* Sometimes we don't notice that a function is a static member, and
       build a METHOD_TYPE for it.  Fix that up now.  */
    if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)
// Build don't link:
// 
// Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 24 April 2001 <nathan@codesourcery.com>

// Bug 2608. A default parameter introduced in the definition of a
// ctor never made it into the clones, leading to later overload
// resolution failures. This is related to bug 2356.

struct A
{
  A (int, int);
};

A::A (int d, int = 0)
{
  if (d)
    {
      A a (0);
    }
}

void get_width ()
{
  A a (1);
}

struct B : A
{
  B ();
};
B::B ()
  :A (1)
{
}

struct C : virtual A
{
  C (int, int);
};
C::C (int, int = 0)
  :A (1)
{
}
struct D: C
{
  D ();
};
D::D ()
  :A (0), C (0)
{
}

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