OSDN Git Service

cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 27 Apr 2001 10:47:36 +0000 (10:47 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 27 Apr 2001 10:47:36 +0000 (10:47 +0000)
* 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.
testsuite:
* g++.old-deja/g++.other/defarg9.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41625 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.other/defarg9.C [new file with mode: 0644]

index c6e06ac..7dc59bf 100644 (file)
@@ -1,3 +1,9 @@
+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.
+
 2001-04-26  Mark Mitchell  <mark@codesourcery.com>
 
        * method.c (use_thunk): Make sure that thunks really are emitted
index 9c713c0..6db4f78 100644 (file)
@@ -4407,6 +4407,80 @@ clone_function_decl (fn, update_method_vec_p)
   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 ef12e1e..a8b22a4 100644 (file)
@@ -3759,6 +3759,7 @@ extern tree build_expr_type_conversion            PARAMS ((int, tree, int));
 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 ea37eb4..246cbd7 100644 (file)
@@ -13345,6 +13345,12 @@ start_function (declspecs, declarator, attrs, flags)
        }
     }
 
+  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)
index 3449dde..1f7bb78 100644 (file)
@@ -1,3 +1,7 @@
+2001-04-27  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.other/defarg9.C: New test.
+
 2001-04-26  Toon Moene  <toon@moene.indiv.nluug.nl>
 
        * g77.f-torture/compile/20010426.f: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.other/defarg9.C b/gcc/testsuite/g++.old-deja/g++.other/defarg9.C
new file mode 100644 (file)
index 0000000..f3b0a48
--- /dev/null
@@ -0,0 +1,52 @@
+// 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)
+{
+}