error.c (dump_function_name): Don't let the user see __comp_ctor.

* 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.

From-SVN: r38158
This commit is contained in:
Jason Merrill 2000-12-09 13:34:12 -05:00 committed by Jason Merrill
parent 193ad8c673
commit 5e818b9351
8 changed files with 128 additions and 82 deletions

View File

@ -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>

View File

@ -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);
}

View File

@ -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),

View File

@ -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, '~');

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;