aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2001-04-27 10:47:36 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2001-04-27 10:47:36 +0000
commit5f6eeeb3625bd5121465d8a50c89f47b25af0a69 (patch)
tree0db5d6c3a3f6dcb5dd8296b756654750fccb07fa /gcc
parent6e0263244cee6c6158deb4ca00b7ca1d0e4cc193 (diff)
downloadgcc-5f6eeeb3625bd5121465d8a50c89f47b25af0a69.zip
gcc-5f6eeeb3625bd5121465d8a50c89f47b25af0a69.tar.gz
gcc-5f6eeeb3625bd5121465d8a50c89f47b25af0a69.tar.bz2
cp-tree.h (adjust_clone_args): Prototype new function.
cp: * 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. From-SVN: r41625
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/class.c74
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c6
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/defarg9.C52
6 files changed, 143 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c6e06ac..7dc59bf 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 9c713c0..6db4f78 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ef12e1e..a8b22a4 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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 */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ea37eb4..246cbd7 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3449dde..1f7bb78 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..f3b0a48
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/defarg9.C
@@ -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)
+{
+}