From 4f0aa41654923b227eae756fec96308c0e53ef47 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Wed, 28 Jul 1999 08:20:09 +0000 Subject: [PATCH] call.c (conditional_conversion): Don't build BASE_CONVs for conversions between things that have the same type. * call.c (conditional_conversion): Don't build BASE_CONVs for conversions between things that have the same type. (build_conditional_expr): Tweak. (convert_like): Some BASE_CONVs really do require the generation of code. * init.c (perform_member_init): Don't go through build_modify_expr for simple initializations. From-SVN: r28310 --- gcc/cp/ChangeLog | 11 ++++++ gcc/cp/call.c | 34 +++++++++++++++---- gcc/cp/init.c | 26 ++++++++------ gcc/testsuite/g++.old-deja/g++.other/cond2.C | 11 ++++++ gcc/testsuite/g++.old-deja/g++.other/init14.C | 22 ++++++++++++ gcc/testsuite/g++.old-deja/g++.other/ref3.C | 30 ++++++++++++++++ 6 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/cond2.C create mode 100644 gcc/testsuite/g++.old-deja/g++.other/init14.C create mode 100644 gcc/testsuite/g++.old-deja/g++.other/ref3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 63adc40f37c..3c7ddbd7f95 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +1999-07-28 Mark Mitchell + + * call.c (conditional_conversion): Don't build BASE_CONVs for + conversions between things that have the same type. + (build_conditional_expr): Tweak. + (convert_like): Some BASE_CONVs really do require the generation + of code. + + * init.c (perform_member_init): Don't go through build_modify_expr + for simple initializations. + 1999-07-27 Jason Merrill * cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 1d9e83745d4..4deaac2d5b2 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2716,7 +2716,9 @@ conditional_conversion (e1, e2) if (at_least_as_qualified_p (t2, t1)) { conv = build1 (IDENTITY_CONV, t1, e1); - conv = build_conv (BASE_CONV, t2, conv); + if (!same_type_p (TYPE_MAIN_VARIANT (t1), + TYPE_MAIN_VARIANT (t2))) + conv = build_conv (BASE_CONV, t2, conv); return conv; } else @@ -2865,11 +2867,22 @@ build_conditional_expr (arg1, arg2, arg3) else if (conv2 && !ICS_BAD_FLAG (conv2)) { arg2 = convert_like (conv2, arg2); + /* That may not quite have done the trick. If the two types + are cv-qualified variants of one another, we will have + just used an IDENTITY_CONV. (There's no conversion from + an lvalue of one class type to an lvalue of another type, + even a cv-qualified variant, and we don't want to lose + lvalue-ness here.) So, we manually add a NOP_EXPR here + if necessary. */ + if (!same_type_p (TREE_TYPE (arg2), arg3_type)) + arg2 = build1 (NOP_EXPR, arg3_type, arg2); arg2_type = TREE_TYPE (arg2); } else if (conv3 && !ICS_BAD_FLAG (conv3)) { arg3 = convert_like (conv3, arg3); + if (!same_type_p (TREE_TYPE (arg3), arg2_type)) + arg2 = build1 (NOP_EXPR, arg2_type, arg3); arg3_type = TREE_TYPE (arg3); } } @@ -3647,12 +3660,19 @@ convert_like (convs, expr) return expr; /* else fall through */ case BASE_CONV: - if (TREE_CODE (convs) == BASE_CONV - && !NEED_TEMPORARY_P (convs)) - /* We are going to bind a reference directly to a base-class - subobject of EXPR. We don't have to generate any code - here. */ - return expr; + if (TREE_CODE (convs) == BASE_CONV && !NEED_TEMPORARY_P (convs)) + { + /* We are going to bind a reference directly to a base-class + subobject of EXPR. */ + tree base_ptr = build_pointer_type (TREE_TYPE (convs)); + + /* Build an expression for `*((base*) &expr)'. */ + expr = build_unary_op (ADDR_EXPR, expr, 0); + expr = perform_implicit_conversion (base_ptr, expr); + expr = build_indirect_ref (expr, "implicit conversion"); + return expr; + } + { tree cvt_expr = build_user_type_conversion (TREE_TYPE (convs), expr, LOOKUP_NORMAL); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index b3b9dcb0bc9..4163b1b8949 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -194,13 +194,21 @@ perform_member_init (member, name, init, explicit) { /* default-initialization. */ if (AGGREGATE_TYPE_P (type)) - init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); - else if (TREE_CODE (type) == REFERENCE_TYPE) { - cp_error ("default-initialization of `%#D', which has reference type", - member); - init = error_mark_node; + /* This is a default initialization of an aggregate, + but not one of non-POD class type. We cleverly + notice that the initialization rules in such a + case are the same as for initialization with an + empty brace-initialization list. We don't want + to call build_modify_expr as that will go looking + for constructors and such. */ + tree e = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); + TREE_SIDE_EFFECTS (e) = 1; + expand_expr_stmt (build (INIT_EXPR, type, decl, e)); } + else if (TREE_CODE (type) == REFERENCE_TYPE) + cp_error ("default-initialization of `%#D', which has reference type", + member); else init = integer_zero_node; } @@ -221,12 +229,8 @@ perform_member_init (member, name, init, explicit) init = TREE_VALUE (init); } - /* We only build this with a null init if we got it from the - current_member_init_list. */ - if (init || explicit) - { - expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); - } + if (init) + expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); } expand_end_target_temps (); diff --git a/gcc/testsuite/g++.old-deja/g++.other/cond2.C b/gcc/testsuite/g++.old-deja/g++.other/cond2.C new file mode 100644 index 00000000000..a83273fa674 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/cond2.C @@ -0,0 +1,11 @@ +// Build don't link: +// Origin: Loring Holden + +class Wpt {}; + +class RAYhit { + protected: + Wpt _nearpt; + public: + Wpt surf () const { return true ? Wpt(): _nearpt; } +}; diff --git a/gcc/testsuite/g++.old-deja/g++.other/init14.C b/gcc/testsuite/g++.old-deja/g++.other/init14.C new file mode 100644 index 00000000000..8c866d79e4b --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/init14.C @@ -0,0 +1,22 @@ +// Build don't link: +// Origin: bkoz@nabi.net + +typedef struct +{ + int count; +} mbstate_t; + +struct fpos +{ + mbstate_t _M_st; + fpos(int __pos) + : _M_st() { + } +}; + +int main () +{ + fpos f (2); +} + + diff --git a/gcc/testsuite/g++.old-deja/g++.other/ref3.C b/gcc/testsuite/g++.old-deja/g++.other/ref3.C new file mode 100644 index 00000000000..6d615d4ce99 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/ref3.C @@ -0,0 +1,30 @@ +// Origin: Mark Mitchell + +struct B1 +{ + int i; +}; + +struct B2 +{ + int j; +}; + +struct D: public B1, B2 +{ +}; + +bool f (B2& b) +{ + return b.j == 7; +} + +int main () +{ + D d; + d.i = 2; + d.j = 7; + if (!f (d)) + return 1; +} + -- 2.30.2