Commit 5e818b93 by Jason Merrill Committed by Jason Merrill

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
parent 193ad8c6
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> 2000-12-07 Nathan Sidwell <nathan@codesourcery.com>
* class.c (check_field_decls): Don't special case anonymous * class.c (check_field_decls): Don't special case anonymous
...@@ -96,8 +114,6 @@ ...@@ -96,8 +114,6 @@
* except.c (expand_throw): Use push_throw_library_fn for _Jv_Throw. * 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. * class.c (clone_function_decl): Robustify.
2000-12-04 Michael Matz <matzmich@cs.tu-berlin.de> 2000-12-04 Michael Matz <matzmich@cs.tu-berlin.de>
......
...@@ -1237,29 +1237,18 @@ implicit_conversion (to, from, expr, flags) ...@@ -1237,29 +1237,18 @@ implicit_conversion (to, from, expr, flags)
if (conv) if (conv)
; ;
else if (expr != NULL_TREE else if (expr != NULL_TREE
&& (IS_AGGR_TYPE (non_reference (from)) && (IS_AGGR_TYPE (from)
|| IS_AGGR_TYPE (non_reference (to))) || IS_AGGR_TYPE (to))
&& (flags & LOOKUP_NO_CONVERSION) == 0) && (flags & LOOKUP_NO_CONVERSION) == 0)
{ {
cand = build_user_type_conversion_1 cand = build_user_type_conversion_1
(to, expr, LOOKUP_ONLYCONVERTING); (to, expr, LOOKUP_ONLYCONVERTING);
if (cand) if (cand)
conv = cand->second_conv; conv = cand->second_conv;
if ((! conv || ICS_BAD_FLAG (conv))
&& TREE_CODE (to) == REFERENCE_TYPE /* We used to try to bind a reference to a temporary here, but that
&& (flags & LOOKUP_NO_TEMP_BIND) == 0) is now handled by the recursive call to this function at the end
{ of reference_binding. */
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);
}
}
} }
return conv; return conv;
...@@ -2325,6 +2314,13 @@ build_user_type_conversion_1 (totype, expr, flags) ...@@ -2325,6 +2314,13 @@ build_user_type_conversion_1 (totype, expr, flags)
tree args = NULL_TREE; tree args = NULL_TREE;
tree templates = 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)) if (IS_AGGR_TYPE (totype))
ctors = lookup_fnfields (TYPE_BINFO (totype), ctors = lookup_fnfields (TYPE_BINFO (totype),
(flag_new_abi (flag_new_abi
...@@ -2332,8 +2328,7 @@ build_user_type_conversion_1 (totype, expr, flags) ...@@ -2332,8 +2328,7 @@ build_user_type_conversion_1 (totype, expr, flags)
: ctor_identifier), : ctor_identifier),
0); 0);
if (IS_AGGR_TYPE (fromtype) if (IS_AGGR_TYPE (fromtype))
&& (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
convs = lookup_conversions (fromtype); convs = lookup_conversions (fromtype);
candidates = 0; candidates = 0;
...@@ -2509,9 +2504,7 @@ build_user_type_conversion (totype, expr, flags) ...@@ -2509,9 +2504,7 @@ build_user_type_conversion (totype, expr, flags)
{ {
if (TREE_CODE (cand->second_conv) == AMBIG_CONV) if (TREE_CODE (cand->second_conv) == AMBIG_CONV)
return error_mark_node; return error_mark_node;
return convert_from_reference return convert_from_reference (convert_like (cand->second_conv, expr));
(convert_like_with_context
(cand->second_conv, expr, cand->fn, 0));
} }
return NULL_TREE; return NULL_TREE;
} }
...@@ -3653,6 +3646,11 @@ convert_like_real (convs, expr, fn, argnum, inner) ...@@ -3653,6 +3646,11 @@ convert_like_real (convs, expr, fn, argnum, inner)
int argnum; int argnum;
int inner; int inner;
{ {
extern int warningcount, errorcount;
int savew, savee;
tree totype = TREE_TYPE (convs);
if (ICS_BAD_FLAG (convs) if (ICS_BAD_FLAG (convs)
&& TREE_CODE (convs) != USER_CONV && TREE_CODE (convs) != USER_CONV
&& TREE_CODE (convs) != AMBIG_CONV && TREE_CODE (convs) != AMBIG_CONV
...@@ -3672,29 +3670,29 @@ convert_like_real (convs, expr, fn, argnum, inner) ...@@ -3672,29 +3670,29 @@ convert_like_real (convs, expr, fn, argnum, inner)
break; break;
} }
return convert_for_initialization return convert_for_initialization
(NULL_TREE, TREE_TYPE (convs), expr, LOOKUP_NORMAL, (NULL_TREE, totype, expr, LOOKUP_NORMAL,
"conversion", fn, argnum); "conversion", fn, argnum);
} }
if (!inner) if (!inner)
expr = dubious_conversion_warnings expr = dubious_conversion_warnings
(TREE_TYPE (convs), expr, "argument", fn, argnum); (totype, expr, "argument", fn, argnum);
switch (TREE_CODE (convs)) switch (TREE_CODE (convs))
{ {
case USER_CONV: case USER_CONV:
{ {
struct z_candidate *cand struct z_candidate *cand
= WRAPPER_PTR (TREE_OPERAND (convs, 1)); = WRAPPER_PTR (TREE_OPERAND (convs, 1));
tree fn = cand->fn; tree convfn = cand->fn;
tree args; tree args;
if (DECL_CONSTRUCTOR_P (fn)) if (DECL_CONSTRUCTOR_P (convfn))
{ {
tree t = build_int_2 (0, 0); 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); 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, integer_one_node, args);
args = tree_cons (NULL_TREE, t, args); args = tree_cons (NULL_TREE, t, args);
} }
...@@ -3704,19 +3702,61 @@ convert_like_real (convs, expr, fn, argnum, inner) ...@@ -3704,19 +3702,61 @@ convert_like_real (convs, expr, fn, argnum, inner)
/* If this is a constructor or a function returning an aggr type, /* If this is a constructor or a function returning an aggr type,
we need to build up a TARGET_EXPR. */ we need to build up a TARGET_EXPR. */
if (DECL_CONSTRUCTOR_P (fn)) if (DECL_CONSTRUCTOR_P (convfn))
expr = build_cplus_new (TREE_TYPE (convs), expr); 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; return expr;
} }
case IDENTITY_CONV: case IDENTITY_CONV:
if (type_unknown_p (expr)) if (type_unknown_p (expr))
expr = instantiate_type (TREE_TYPE (convs), expr, itf_complain); expr = instantiate_type (totype, expr, itf_complain);
return expr; return expr;
case AMBIG_CONV: case AMBIG_CONV:
/* Call build_user_type_conversion again for the error. */ /* Call build_user_type_conversion again for the error. */
return build_user_type_conversion return build_user_type_conversion
(TREE_TYPE (convs), TREE_OPERAND (convs, 0), LOOKUP_NORMAL); (totype, TREE_OPERAND (convs, 0), LOOKUP_NORMAL);
default: default:
break; break;
...@@ -3736,7 +3776,7 @@ convert_like_real (convs, expr, fn, argnum, inner) ...@@ -3736,7 +3776,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
switch (TREE_CODE (convs)) switch (TREE_CODE (convs))
{ {
case RVALUE_CONV: case RVALUE_CONV:
if (! IS_AGGR_TYPE (TREE_TYPE (convs))) if (! IS_AGGR_TYPE (totype))
return expr; return expr;
/* else fall through */ /* else fall through */
case BASE_CONV: case BASE_CONV:
...@@ -3744,7 +3784,7 @@ convert_like_real (convs, expr, fn, argnum, inner) ...@@ -3744,7 +3784,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
{ {
/* We are going to bind a reference directly to a base-class /* We are going to bind a reference directly to a base-class
subobject of EXPR. */ 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)'. */ /* Build an expression for `*((base*) &expr)'. */
expr = build_unary_op (ADDR_EXPR, expr, 0); expr = build_unary_op (ADDR_EXPR, expr, 0);
...@@ -3753,35 +3793,27 @@ convert_like_real (convs, expr, fn, argnum, inner) ...@@ -3753,35 +3793,27 @@ convert_like_real (convs, expr, fn, argnum, inner)
return expr; return expr;
} }
{ /* Copy-initialization where the cv-unqualified version of the source
tree cvt_expr = build_user_type_conversion type is the same class as, or a derived class of, the class of the
(TREE_TYPE (convs), expr, LOOKUP_NORMAL); destination [is treated as direct-initialization]. [dcl.init] */
if (!cvt_expr) if (fn)
{ savew = warningcount, savee = errorcount;
/* This can occur if, for example, the EXPR has incomplete expr = build_new_method_call (NULL_TREE, complete_ctor_identifier,
type. We can't check for that before attempting the build_tree_list (NULL_TREE, expr),
conversion because the type might be an incomplete TYPE_BINFO (totype),
array type, which is OK if some constructor for the LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
destination type takes a pointer argument. */ if (fn)
if (!COMPLETE_TYPE_P (TREE_TYPE (expr))) {
{ if (warningcount > savew)
if (same_type_p (TREE_TYPE (expr), TREE_TYPE (convs))) cp_warning (" initializing argument %P of `%D'", argnum, fn);
incomplete_type_error (expr, TREE_TYPE (expr)); else if (errorcount > savee)
else cp_error (" initializing argument %P of `%D'", argnum, fn);
cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'", }
expr, TREE_TYPE (expr), TREE_TYPE (convs)); return build_cplus_new (totype, expr);
}
else
cp_error ("could not convert `%E' to `%T'",
expr, TREE_TYPE (convs));
return error_mark_node;
}
return cvt_expr;
}
case REF_BIND: case REF_BIND:
{ {
tree ref_type = TREE_TYPE (convs); tree ref_type = totype;
/* If necessary, create a temporary. */ /* If necessary, create a temporary. */
if (NEED_TEMPORARY_P (convs)) if (NEED_TEMPORARY_P (convs))
...@@ -3812,13 +3844,13 @@ convert_like_real (convs, expr, fn, argnum, inner) ...@@ -3812,13 +3844,13 @@ convert_like_real (convs, expr, fn, argnum, inner)
case QUAL_CONV: case QUAL_CONV:
/* Warn about deprecated conversion if appropriate. */ /* Warn about deprecated conversion if appropriate. */
string_conv_p (TREE_TYPE (convs), expr, 1); string_conv_p (totype, expr, 1);
break; break;
default: default:
break; break;
} }
return ocp_convert (TREE_TYPE (convs), expr, CONV_IMPLICIT, return ocp_convert (totype, expr, CONV_IMPLICIT,
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
} }
......
...@@ -841,7 +841,7 @@ ocp_convert (type, expr, convtype, flags) ...@@ -841,7 +841,7 @@ ocp_convert (type, expr, convtype, flags)
with a user-defined conversion sequence, then we direct-initialize with a user-defined conversion sequence, then we direct-initialize
the target with the temp (see [dcl.init]). */ the target with the temp (see [dcl.init]). */
ctor = build_user_type_conversion (type, ctor, flags); ctor = build_user_type_conversion (type, ctor, flags);
if (ctor) else
ctor = build_method_call (NULL_TREE, ctor = build_method_call (NULL_TREE,
complete_ctor_identifier, complete_ctor_identifier,
build_tree_list (NULL_TREE, ctor), build_tree_list (NULL_TREE, ctor),
......
...@@ -1340,6 +1340,11 @@ dump_function_name (t, flags) ...@@ -1340,6 +1340,11 @@ dump_function_name (t, flags)
{ {
tree name = DECL_NAME (t); 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)) if (DECL_DESTRUCTOR_P (t))
{ {
output_add_character (scratch_buffer, '~'); output_add_character (scratch_buffer, '~');
......
...@@ -5788,6 +5788,8 @@ tsubst_decl (t, args, type, in_decl) ...@@ -5788,6 +5788,8 @@ tsubst_decl (t, args, type, in_decl)
maybe_retrofit_in_chrg (r); maybe_retrofit_in_chrg (r);
if (DECL_CONSTRUCTOR_P (r)) if (DECL_CONSTRUCTOR_P (r))
grok_ctor_properties (ctx, 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))) else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r)); grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
...@@ -9280,15 +9282,6 @@ do_decl_instantiation (declspecs, declarator, storage) ...@@ -9280,15 +9282,6 @@ do_decl_instantiation (declspecs, declarator, storage)
cp_error ("storage class `%D' applied to template instantiation", cp_error ("storage class `%D' applied to template instantiation",
storage); 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); SET_DECL_EXPLICIT_INSTANTIATION (result);
mark_decl_instantiated (result, extern_p); mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p); repo_template_instantiated (result, extern_p);
......
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
class A class A
{ {
public: public:
A(int j) { i = j; } A(int j) { i = j; } // ERROR - candidate
A(A& a) { i = a.i; } A(A& a) { i = a.i; } // ERROR - candidate
operator int() { return i; } operator int() { return i; }
void assign(int v) { i = v; } void assign(int v) { i = v; }
...@@ -38,10 +38,10 @@ B::run() ...@@ -38,10 +38,10 @@ B::run()
// Replacing above with "switch (int(in))" removes the error. // Replacing above with "switch (int(in))" removes the error.
{ {
case 0: case 0:
out = 1; out = 1; // ERROR - no usable copy ctor
break; break;
default: default:
out = 0; out = 0; // ERROR - no usable copy ctor
break; break;
} }
} }
......
...@@ -4,7 +4,7 @@ int count; ...@@ -4,7 +4,7 @@ int count;
class A { class A {
A(); A();
A(const A&); A(const A&); // ERROR - referenced below
public: public:
A(int) { ++count; } A(int) { ++count; }
~A() { --count; } ~A() { --count; }
...@@ -14,7 +14,7 @@ public: ...@@ -14,7 +14,7 @@ public:
int main() { int main() {
{ {
A a (1); A a (1);
if (a == 2 && a == 1) if (a == 2 && a == 1) // ERROR - private copy ctor
; ;
} }
return count; return count;
......
...@@ -4,7 +4,7 @@ int count; ...@@ -4,7 +4,7 @@ int count;
class A { class A {
A(); A();
A(const A&); A(const A&); // ERROR - referenced below
public: public:
A(int) { ++count; } A(int) { ++count; }
~A() { --count; } ~A() { --count; }
...@@ -14,7 +14,7 @@ public: ...@@ -14,7 +14,7 @@ public:
int main() { int main() {
{ {
A a (1); A a (1);
if (a == 2 || a == 1) if (a == 2 || a == 1) // ERROR - private copy ctor
; ;
} }
return count; return count;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment