diff options
-rw-r--r-- | gcc/cp/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/cp/call.c | 156 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 2 | ||||
-rw-r--r-- | gcc/cp/error.c | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.law/cvt7.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.mike/p5469.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.mike/p5469a.C | 4 |
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; |