summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog20
-rw-r--r--gcc/cp/call.c156
-rw-r--r--gcc/cp/cvt.c2
-rw-r--r--gcc/cp/error.c5
-rw-r--r--gcc/cp/pt.c11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/cvt7.C8
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p5469.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p5469a.C4
8 files changed, 128 insertions, 82 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 00f95491050..0ef0b3d4481 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,21 @@
+2000-12-08 Jason Merrill <jason@redhat.com>
+
+ * error.c (dump_function_name): Don't let the user see __comp_ctor.
+
+ Clean up copy-initialization in overloading code.
+ * call.c (build_user_type_conversion_1): Die if we are asked to
+ convert to the same or a base type.
+ (implicit_conversion): Avoid doing so. Lose reference binding code.
+ (convert_like_real): Treat BASE_CONV and RVALUE_CONV as implicit
+ direct-initialization. Also do direct-init part of copy-init.
+ (build_user_type_conversion): Don't provide context to convert_like.
+ * cvt.c (ocp_convert): build_user_type_conversion will now provide
+ the constructor call for copy-init.
+
+ * pt.c (tsubst_decl): Call clone_function_decl here if this is an
+ instantiation of a member template.
+ (do_decl_instantiation): Not here.
+
2000-12-07 Nathan Sidwell <nathan@codesourcery.com>
* class.c (check_field_decls): Don't special case anonymous
@@ -96,8 +114,6 @@
* except.c (expand_throw): Use push_throw_library_fn for _Jv_Throw.
- * pt.c (tsubst_decl): Call clone_function_decl here.
- (do_decl_instantiation): Not here.
* class.c (clone_function_decl): Robustify.
2000-12-04 Michael Matz <matzmich@cs.tu-berlin.de>
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index cbe345a3f05..2f8a9dc7ed6 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1237,29 +1237,18 @@ implicit_conversion (to, from, expr, flags)
if (conv)
;
else if (expr != NULL_TREE
- && (IS_AGGR_TYPE (non_reference (from))
- || IS_AGGR_TYPE (non_reference (to)))
+ && (IS_AGGR_TYPE (from)
+ || IS_AGGR_TYPE (to))
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
cand = build_user_type_conversion_1
(to, expr, LOOKUP_ONLYCONVERTING);
if (cand)
conv = cand->second_conv;
- if ((! conv || ICS_BAD_FLAG (conv))
- && TREE_CODE (to) == REFERENCE_TYPE
- && (flags & LOOKUP_NO_TEMP_BIND) == 0)
- {
- cand = build_user_type_conversion_1
- (TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING);
- if (cand)
- {
- if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (to)))
- ICS_BAD_FLAG (cand->second_conv) = 1;
- if (!conv || (ICS_BAD_FLAG (conv)
- > ICS_BAD_FLAG (cand->second_conv)))
- conv = build_conv (REF_BIND, to, cand->second_conv);
- }
- }
+
+ /* We used to try to bind a reference to a temporary here, but that
+ is now handled by the recursive call to this function at the end
+ of reference_binding. */
}
return conv;
@@ -2325,6 +2314,13 @@ build_user_type_conversion_1 (totype, expr, flags)
tree args = NULL_TREE;
tree templates = NULL_TREE;
+ /* We represent conversion within a hierarchy using RVALUE_CONV and
+ BASE_CONV, as specified by [over.best.ics]; these become plain
+ constructor calls, as specified in [dcl.init]. */
+ if (IS_AGGR_TYPE (fromtype) && IS_AGGR_TYPE (totype)
+ && DERIVED_FROM_P (totype, fromtype))
+ abort ();
+
if (IS_AGGR_TYPE (totype))
ctors = lookup_fnfields (TYPE_BINFO (totype),
(flag_new_abi
@@ -2332,8 +2328,7 @@ build_user_type_conversion_1 (totype, expr, flags)
: ctor_identifier),
0);
- if (IS_AGGR_TYPE (fromtype)
- && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
+ if (IS_AGGR_TYPE (fromtype))
convs = lookup_conversions (fromtype);
candidates = 0;
@@ -2509,9 +2504,7 @@ build_user_type_conversion (totype, expr, flags)
{
if (TREE_CODE (cand->second_conv) == AMBIG_CONV)
return error_mark_node;
- return convert_from_reference
- (convert_like_with_context
- (cand->second_conv, expr, cand->fn, 0));
+ return convert_from_reference (convert_like (cand->second_conv, expr));
}
return NULL_TREE;
}
@@ -3653,6 +3646,11 @@ convert_like_real (convs, expr, fn, argnum, inner)
int argnum;
int inner;
{
+ extern int warningcount, errorcount;
+ int savew, savee;
+
+ tree totype = TREE_TYPE (convs);
+
if (ICS_BAD_FLAG (convs)
&& TREE_CODE (convs) != USER_CONV
&& TREE_CODE (convs) != AMBIG_CONV
@@ -3672,29 +3670,29 @@ convert_like_real (convs, expr, fn, argnum, inner)
break;
}
return convert_for_initialization
- (NULL_TREE, TREE_TYPE (convs), expr, LOOKUP_NORMAL,
+ (NULL_TREE, totype, expr, LOOKUP_NORMAL,
"conversion", fn, argnum);
}
if (!inner)
expr = dubious_conversion_warnings
- (TREE_TYPE (convs), expr, "argument", fn, argnum);
+ (totype, expr, "argument", fn, argnum);
switch (TREE_CODE (convs))
{
case USER_CONV:
{
struct z_candidate *cand
= WRAPPER_PTR (TREE_OPERAND (convs, 1));
- tree fn = cand->fn;
+ tree convfn = cand->fn;
tree args;
- if (DECL_CONSTRUCTOR_P (fn))
+ if (DECL_CONSTRUCTOR_P (convfn))
{
tree t = build_int_2 (0, 0);
- TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn));
+ TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (convfn));
args = build_tree_list (NULL_TREE, expr);
- if (DECL_HAS_IN_CHARGE_PARM_P (fn))
+ if (DECL_HAS_IN_CHARGE_PARM_P (convfn))
args = tree_cons (NULL_TREE, integer_one_node, args);
args = tree_cons (NULL_TREE, t, args);
}
@@ -3704,19 +3702,61 @@ convert_like_real (convs, expr, fn, argnum, inner)
/* If this is a constructor or a function returning an aggr type,
we need to build up a TARGET_EXPR. */
- if (DECL_CONSTRUCTOR_P (fn))
- expr = build_cplus_new (TREE_TYPE (convs), expr);
+ if (DECL_CONSTRUCTOR_P (convfn))
+ expr = build_cplus_new (totype, expr);
+
+ /* The result of the call is then used to direct-initialize the object
+ that is the destination of the copy-initialization. [dcl.init]
+
+ Note that this step is not reflected in the conversion sequence;
+ it affects the semantics when we actually perform the
+ conversion, but is not considered during overload resolution.
+ If the target is a class, that means call a ctor. */
+ if (IS_AGGR_TYPE (totype))
+ {
+ savew = warningcount, savee = errorcount;
+ expr = build_new_method_call
+ (NULL_TREE, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, expr), TYPE_BINFO (totype),
+ /* Core issue 84, now a DR, says that we don't allow UDCs
+ for these args (which deliberately breaks copy-init of an
+ auto_ptr<Base> from an auto_ptr<Derived>). */
+ LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION);
+
+ /* Tell the user where this failing constructor call came from. */
+ if (fn)
+ {
+ if (warningcount > savew)
+ cp_warning
+ (" initializing argument %P of `%D' from result of `%D'",
+ argnum, fn, convfn);
+ else if (errorcount > savee)
+ cp_error
+ (" initializing argument %P of `%D' from result of `%D'",
+ argnum, fn, convfn);
+ }
+ else
+ {
+ if (warningcount > savew)
+ cp_warning (" initializing temporary from result of `%D'",
+ convfn);
+ else if (errorcount > savee)
+ cp_error (" initializing temporary from result of `%D'",
+ convfn);
+ }
+ expr = build_cplus_new (totype, expr);
+ }
return expr;
}
case IDENTITY_CONV:
if (type_unknown_p (expr))
- expr = instantiate_type (TREE_TYPE (convs), expr, itf_complain);
+ expr = instantiate_type (totype, expr, itf_complain);
return expr;
case AMBIG_CONV:
/* Call build_user_type_conversion again for the error. */
return build_user_type_conversion
- (TREE_TYPE (convs), TREE_OPERAND (convs, 0), LOOKUP_NORMAL);
+ (totype, TREE_OPERAND (convs, 0), LOOKUP_NORMAL);
default:
break;
@@ -3736,7 +3776,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
switch (TREE_CODE (convs))
{
case RVALUE_CONV:
- if (! IS_AGGR_TYPE (TREE_TYPE (convs)))
+ if (! IS_AGGR_TYPE (totype))
return expr;
/* else fall through */
case BASE_CONV:
@@ -3744,7 +3784,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
{
/* We are going to bind a reference directly to a base-class
subobject of EXPR. */
- tree base_ptr = build_pointer_type (TREE_TYPE (convs));
+ tree base_ptr = build_pointer_type (totype);
/* Build an expression for `*((base*) &expr)'. */
expr = build_unary_op (ADDR_EXPR, expr, 0);
@@ -3753,35 +3793,27 @@ convert_like_real (convs, expr, fn, argnum, inner)
return expr;
}
- {
- tree cvt_expr = build_user_type_conversion
- (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
- if (!cvt_expr)
- {
- /* This can occur if, for example, the EXPR has incomplete
- type. We can't check for that before attempting the
- conversion because the type might be an incomplete
- array type, which is OK if some constructor for the
- destination type takes a pointer argument. */
- if (!COMPLETE_TYPE_P (TREE_TYPE (expr)))
- {
- if (same_type_p (TREE_TYPE (expr), TREE_TYPE (convs)))
- incomplete_type_error (expr, TREE_TYPE (expr));
- else
- cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'",
- expr, TREE_TYPE (expr), TREE_TYPE (convs));
- }
- else
- cp_error ("could not convert `%E' to `%T'",
- expr, TREE_TYPE (convs));
- return error_mark_node;
- }
- return cvt_expr;
- }
+ /* 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] */
+ if (fn)
+ savew = warningcount, savee = errorcount;
+ expr = build_new_method_call (NULL_TREE, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, expr),
+ TYPE_BINFO (totype),
+ LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
+ if (fn)
+ {
+ if (warningcount > savew)
+ cp_warning (" initializing argument %P of `%D'", argnum, fn);
+ else if (errorcount > savee)
+ cp_error (" initializing argument %P of `%D'", argnum, fn);
+ }
+ return build_cplus_new (totype, expr);
case REF_BIND:
{
- tree ref_type = TREE_TYPE (convs);
+ tree ref_type = totype;
/* If necessary, create a temporary. */
if (NEED_TEMPORARY_P (convs))
@@ -3812,13 +3844,13 @@ convert_like_real (convs, expr, fn, argnum, inner)
case QUAL_CONV:
/* Warn about deprecated conversion if appropriate. */
- string_conv_p (TREE_TYPE (convs), expr, 1);
+ string_conv_p (totype, expr, 1);
break;
default:
break;
}
- return ocp_convert (TREE_TYPE (convs), expr, CONV_IMPLICIT,
+ return ocp_convert (totype, expr, CONV_IMPLICIT,
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
}
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 1672f26f82b..e997d11d7bf 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -841,7 +841,7 @@ ocp_convert (type, expr, convtype, flags)
with a user-defined conversion sequence, then we direct-initialize
the target with the temp (see [dcl.init]). */
ctor = build_user_type_conversion (type, ctor, flags);
- if (ctor)
+ else
ctor = build_method_call (NULL_TREE,
complete_ctor_identifier,
build_tree_list (NULL_TREE, ctor),
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 92953b9bf15..b208e653f2c 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1340,6 +1340,11 @@ dump_function_name (t, flags)
{
tree name = DECL_NAME (t);
+ /* Don't let the user see __comp_ctor et al. */
+ if (DECL_CONSTRUCTOR_P (t)
+ || DECL_DESTRUCTOR_P (t))
+ name = constructor_name (DECL_CONTEXT (t));
+
if (DECL_DESTRUCTOR_P (t))
{
output_add_character (scratch_buffer, '~');
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 900ef3c6c62..87d4195b317 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5788,6 +5788,8 @@ tsubst_decl (t, args, type, in_decl)
maybe_retrofit_in_chrg (r);
if (DECL_CONSTRUCTOR_P (r))
grok_ctor_properties (ctx, r);
+ if (PRIMARY_TEMPLATE_P (gen_tmpl))
+ clone_function_decl(r, /*update_method_vec_p=*/0);
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
@@ -9280,15 +9282,6 @@ do_decl_instantiation (declspecs, declarator, storage)
cp_error ("storage class `%D' applied to template instantiation",
storage);
- /* Under the new ABI, we need to make sure to instantiate all the
- cloned versions of constructors or destructors. */
- if (flag_new_abi &&
- (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (result) ||
- DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (result)) &&
- !(TREE_CHAIN (result) &&
- DECL_CLONED_FUNCTION (TREE_CHAIN (result))))
- clone_function_decl(result, /*update_method_vec_p=*/0);
-
SET_DECL_EXPLICIT_INSTANTIATION (result);
mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p);
diff --git a/gcc/testsuite/g++.old-deja/g++.law/cvt7.C b/gcc/testsuite/g++.old-deja/g++.law/cvt7.C
index 99fe2555446..fc775c4f079 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/cvt7.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/cvt7.C
@@ -11,8 +11,8 @@
class A
{
public:
- A(int j) { i = j; }
- A(A& a) { i = a.i; }
+ A(int j) { i = j; } // ERROR - candidate
+ A(A& a) { i = a.i; } // ERROR - candidate
operator int() { return i; }
void assign(int v) { i = v; }
@@ -38,10 +38,10 @@ B::run()
// Replacing above with "switch (int(in))" removes the error.
{
case 0:
- out = 1;
+ out = 1; // ERROR - no usable copy ctor
break;
default:
- out = 0;
+ out = 0; // ERROR - no usable copy ctor
break;
}
}
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p5469.C b/gcc/testsuite/g++.old-deja/g++.mike/p5469.C
index 9af20101171..9e5250e43de 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p5469.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p5469.C
@@ -4,7 +4,7 @@ int count;
class A {
A();
- A(const A&);
+ A(const A&); // ERROR - referenced below
public:
A(int) { ++count; }
~A() { --count; }
@@ -14,7 +14,7 @@ public:
int main() {
{
A a (1);
- if (a == 2 && a == 1)
+ if (a == 2 && a == 1) // ERROR - private copy ctor
;
}
return count;
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p5469a.C b/gcc/testsuite/g++.old-deja/g++.mike/p5469a.C
index 0783f77dffe..9cbd2dfe7a8 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p5469a.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p5469a.C
@@ -4,7 +4,7 @@ int count;
class A {
A();
- A(const A&);
+ A(const A&); // ERROR - referenced below
public:
A(int) { ++count; }
~A() { --count; }
@@ -14,7 +14,7 @@ public:
int main() {
{
A a (1);
- if (a == 2 || a == 1)
+ if (a == 2 || a == 1) // ERROR - private copy ctor
;
}
return count;