This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [c++] gcc-2.96(today) broken ctor-initializers
- To: bkoz at nabi dot net
- Subject: Re: [c++] gcc-2.96(today) broken ctor-initializers
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Wed, 28 Jul 1999 01:20:43 -0700
- Cc: gcc-patches at gcc dot gnu dot org, bkoz at cygnus dot com, Loring Holden <lsh at cs dot brown dot edu>
- Organization: CodeSourcery, LLC
- References: <379E936E.9FD1CF92@nabi.net>
Here's a patch to undo some of the damage I've done over the last
couple of days. :-)
This should fix the problem Loring reported with conditional
expressions, the one Benjamin reported with member initializers, and
one bad conversion bug I found all by myself.
The way we were handling default initialization was truly obscure; we
were finding that we were initializing a class without constructors,
then called its constructor (passing it a CONSTRUCTOR), which caused
us to create myriad TARGET_EXPRs all of which we then cleverly
optimized away to get back where we started. Nifty, but not as
circumspect as one might hope for. :-) Now, we just build an
INIT_EXPR and get on with life.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
1999-07-28 Mark Mitchell <mark@codesourcery.com>
* 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.
Index: cond2.C
===================================================================
RCS file: cond2.C
diff -N cond2.C
*** /dev/null Sat Dec 5 20:30:03 1998
--- cond2.C Wed Jul 28 01:09:48 1999
***************
*** 0 ****
--- 1,11 ----
+ // Build don't link:
+ // Origin: Loring Holden <lsh@cs.brown.edu>
+
+ class Wpt {};
+
+ class RAYhit {
+ protected:
+ Wpt _nearpt;
+ public:
+ Wpt surf () const { return true ? Wpt(): _nearpt; }
+ };
Index: init14.C
===================================================================
RCS file: init14.C
diff -N init14.C
*** /dev/null Sat Dec 5 20:30:03 1998
--- init14.C Wed Jul 28 01:09:48 1999
***************
*** 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);
+ }
+
+
Index: ref3.C
===================================================================
RCS file: ref3.C
diff -N ref3.C
*** /dev/null Sat Dec 5 20:30:03 1998
--- ref3.C Wed Jul 28 01:09:48 1999
***************
*** 0 ****
--- 1,30 ----
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+
+ 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;
+ }
+
Index: call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.153
diff -c -p -r1.153 call.c
*** call.c 1999/07/26 18:12:15 1.153
--- call.c 1999/07/28 07:53:35
*************** conditional_conversion (e1, e2)
*** 2716,2722 ****
if (at_least_as_qualified_p (t2, t1))
{
conv = build1 (IDENTITY_CONV, t1, e1);
! conv = build_conv (BASE_CONV, t2, conv);
return conv;
}
else
--- 2716,2724 ----
if (at_least_as_qualified_p (t2, t1))
{
conv = build1 (IDENTITY_CONV, t1, e1);
! if (!same_type_p (TYPE_MAIN_VARIANT (t1),
! TYPE_MAIN_VARIANT (t2)))
! conv = build_conv (BASE_CONV, t2, conv);
return conv;
}
else
*************** build_conditional_expr (arg1, arg2, arg3
*** 2865,2875 ****
--- 2867,2888 ----
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);
}
}
*************** convert_like (convs, expr)
*** 3647,3658 ****
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;
{
tree cvt_expr = build_user_type_conversion
(TREE_TYPE (convs), expr, LOOKUP_NORMAL);
--- 3660,3678 ----
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. */
! 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);
Index: init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.114
diff -c -p -r1.114 init.c
*** init.c 1999/07/26 08:18:17 1.114
--- init.c 1999/07/28 07:53:37
*************** perform_member_init (member, name, init,
*** 194,206 ****
{
/* 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;
}
else
init = integer_zero_node;
}
--- 195,215 ----
{
/* default-initialization. */
if (AGGREGATE_TYPE_P (type))
{
! /* 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;
}
*************** perform_member_init (member, name, init,
*** 221,232 ****
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));
! }
}
expand_end_target_temps ();
--- 230,237 ----
init = TREE_VALUE (init);
}
! if (init)
! expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
}
expand_end_target_temps ();