This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH]: Reference binding of packed fields
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 16 Jul 2003 11:50:34 +0100
- Subject: [C++ PATCH]: Reference binding of packed fields
- Organization: Codesourcery LLC
Hi,
this patch prevents non-const reference bindings to packed fields.
It also prevents packing fields of non-pod type when the POD is
not packed itself.
Whilst, rth's comment 'don't do that then' is fine for explicitly taking
the address of a packed field, C++ reference binding happens much more
quietly, and some machines silently ignore the LSBs of an unaligned
memory address - bleah!
booted & tested on i686-pc-linux-gnu, ok?
nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
The voices in my head said this was stupid too
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk
2003-07-16 Nathan Sidwell <nathan@codesourcery.com>
* cp-tree.h (enum cp_lvalue_kind): Add clk_packed.
* tree.c (lvalue_p_1): Set it.
* class.c (check_field): Don't allow non-packed non-POD fields to
be packed.
* call.c (reference_binding): Need a temporary for all bitfield
and packed fields.
(convert_like_real): Check it is ok to make a temporary here.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.407
diff -c -3 -p -r1.407 call.c
*** cp/call.c 14 Jul 2003 17:45:07 -0000 1.407
--- cp/call.c 16 Jul 2003 10:26:29 -0000
*************** reference_binding (tree rto, tree rfrom,
*** 1054,1063 ****
lvalue. */
conv = build1 (IDENTITY_CONV, from, expr);
conv = direct_reference_binding (rto, conv);
! if ((lvalue_p & clk_bitfield) != 0
! && CP_TYPE_CONST_NON_VOLATILE_P (to))
/* For the purposes of overload resolution, we ignore the fact
! this expression is a bitfield. (In particular,
[over.ics.ref] says specifically that a function with a
non-const reference parameter is viable even if the
argument is a bitfield.)
--- 1054,1063 ----
lvalue. */
conv = build1 (IDENTITY_CONV, from, expr);
conv = direct_reference_binding (rto, conv);
! if ((lvalue_p & clk_bitfield) != 0
! || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
/* For the purposes of overload resolution, we ignore the fact
! this expression is a bitfield or packed field. (In particular,
[over.ics.ref] says specifically that a function with a
non-const reference parameter is viable even if the
argument is a bitfield.)
*************** reference_binding (tree rto, tree rfrom,
*** 1068,1073 ****
--- 1068,1074 ----
a temporary, so we just issue an error when the conversion
actually occurs. */
NEED_TEMPORARY_P (conv) = 1;
+
return conv;
}
else if (CLASS_TYPE_P (from) && !(flags & LOOKUP_NO_CONVERSION))
*************** convert_like_real (tree convs, tree expr
*** 4175,4180 ****
--- 4176,4198 ----
if (NEED_TEMPORARY_P (convs) || !non_cast_lvalue_p (expr))
{
tree type = TREE_TYPE (TREE_OPERAND (convs, 0));
+
+ if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
+ {
+ /* If the reference is volatile or non-const, we
+ cannot create a temporary. */
+ cp_lvalue_kind lvalue = real_lvalue_p (expr);
+
+ if (lvalue & clk_bitfield)
+ error ("cannot bind bitfield `%E' to `%T'",
+ expr, ref_type);
+ else if (lvalue & clk_packed)
+ error ("cannot bind packed field `%E' to `%T'",
+ expr, ref_type);
+ else
+ my_friendly_assert (0, 20030715);
+ return error_mark_node;
+ }
expr = build_target_expr_with_type (expr, type);
}
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.552
diff -c -3 -p -r1.552 class.c
*** cp/class.c 14 Jul 2003 05:12:54 -0000 1.552
--- cp/class.c 16 Jul 2003 10:26:46 -0000
*************** check_field_decls (tree t, tree *access_
*** 3022,3028 ****
if (TREE_CODE (x) == FIELD_DECL)
{
! DECL_PACKED (x) |= TYPE_PACKED (t);
if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
/* We don't treat zero-width bitfields as making a class
--- 3022,3036 ----
if (TREE_CODE (x) == FIELD_DECL)
{
! if (TYPE_PACKED (t))
! {
! if (!pod_type_p (TREE_TYPE (x)) && !TYPE_PACKED (TREE_TYPE (x)))
! cp_warning_at
! ("ignoring packed attribute on unpacked non-POD field `%#D'",
! x);
! else
! DECL_PACKED (x) = 1;
! }
if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
/* We don't treat zero-width bitfields as making a class
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.877
diff -c -3 -p -r1.877 cp-tree.h
*** cp/cp-tree.h 14 Jul 2003 19:05:01 -0000 1.877
--- cp/cp-tree.h 16 Jul 2003 10:26:58 -0000
*************** typedef enum cp_lvalue_kind {
*** 2949,2955 ****
clk_none = 0, /* Things that are not an lvalue. */
clk_ordinary = 1, /* An ordinary lvalue. */
clk_class = 2, /* An rvalue of class-type. */
! clk_bitfield = 4 /* An lvalue for a bit-field. */
} cp_lvalue_kind;
/* The kinds of scopes we recognize. */
--- 2949,2956 ----
clk_none = 0, /* Things that are not an lvalue. */
clk_ordinary = 1, /* An ordinary lvalue. */
clk_class = 2, /* An rvalue of class-type. */
! clk_bitfield = 4, /* An lvalue for a bit-field. */
! clk_packed = 8 /* An lvalue for a packed field. */
} cp_lvalue_kind;
/* The kinds of scopes we recognize. */
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.336
diff -c -3 -p -r1.336 tree.c
*** cp/tree.c 10 Jul 2003 16:47:48 -0000 1.336
--- cp/tree.c 16 Jul 2003 10:27:32 -0000
*************** lvalue_p_1 (tree ref,
*** 100,110 ****
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues,
allow_cast_as_lvalue);
! if (op1_lvalue_kind
! /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
! situations. */
! && TREE_CODE (TREE_OPERAND (ref, 1)) == FIELD_DECL
! && DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
{
/* Clear the ordinary bit. If this object was a class
rvalue we want to preserve that information. */
--- 100,111 ----
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues,
allow_cast_as_lvalue);
! if (!op1_lvalue_kind
! /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
! situations. */
! || TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL)
! ;
! else if (DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
{
/* Clear the ordinary bit. If this object was a class
rvalue we want to preserve that information. */
*************** lvalue_p_1 (tree ref,
*** 112,117 ****
--- 113,121 ----
/* The lvalue is for a btifield. */
op1_lvalue_kind |= clk_bitfield;
}
+ else if (DECL_PACKED (TREE_OPERAND (ref, 1)))
+ op1_lvalue_kind |= clk_packed;
+
return op1_lvalue_kind;
case STRING_CST:
// { dg-do compile }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 15 Jul 2003 <nathan@codesourcery.com>
// Packed fields are unsuitable for direct reference binding.
struct Unpacked { int i; };
void Ref (int &p);
void Ref (Unpacked &p);
struct __attribute__ ((packed)) Packed
{
char c;
int i;
Unpacked u;
};
void Foo (Packed &p)
{
Ref (p.i); // { dg-error "cannot bind packed field" "" }
Ref (p.u.i); // { dg-error "cannot bind packed field" "" }
Ref (p.u); // { dg-error "cannot bind packed field" "" }
}
// { dg-do run }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 15 Jul 2003 <nathan@codesourcery.com>
// Packed fields are unsuitable for direct reference binding.
struct Unpacked { int i; };
int ConstRef (int const &p, int const *ptr, int v)
{
if (p != v)
return 1;
if (&p == ptr)
return 2;
return 0;
}
int ConstRef (Unpacked const &p, Unpacked const *ptr, int v)
{
if (p.i != v)
return 1;
if (&p == ptr)
return 2;
return 0;
}
int Val (int p, int v)
{
if (p != v)
return 1;
return 0;
}
int Val (Unpacked p, int v)
{
if (p.i != v)
return 1;
return 0;
}
struct __attribute__ ((packed)) Packed
{
char c;
int i;
Unpacked u;
char t;
};
int Foo (Packed &p, int i, int ui)
{
int r;
if ((r = Val (p.i, i)))
return r;
if ((r = Val (p.u.i, ui)))
return r + 2;
if ((r = Val (p.u, ui)))
return r + 4;
if ((r = ConstRef (p.i, &p.i, i)))
return r + 6;
if ((r = ConstRef (p.u.i, &p.u.i, ui)))
return r + 8;
if ((r = ConstRef (p.u, &p.u, ui)))
return r + 10;
return 0;
}
int main ()
{
Packed p;
p.c = 0x12;
p.i = 0x3456789a;
p.u.i = 0xbcdef00f;
p.t = 0xed;
return Foo (p, 0x3456789a, 0xbcdef00f);
}