diff options
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/call.c | 24 | ||||
-rw-r--r-- | gcc/cp/class.c | 10 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/tree.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/packed3.C | 25 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/packed4.C | 80 |
8 files changed, 159 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d13909b..d7a5966 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2003-07-22 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. + 2003-07-21 Nathan Sidwell <nathan@codesourcery.com> * cp-tree.h (hack_identifier): Remove. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 013d600..022ac78 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1054,10 +1054,10 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags) 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)) + 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. (In particular, + 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.) @@ -1068,6 +1068,7 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags) 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)) @@ -4172,6 +4173,23 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner, 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); } diff --git a/gcc/cp/class.c b/gcc/cp/class.c index b9f139f..06cb635 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2959,7 +2959,15 @@ check_field_decls (tree t, tree *access_decls, if (TREE_CODE (x) == FIELD_DECL) { - DECL_PACKED (x) |= TYPE_PACKED (t); + 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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 29a9f29..8fef2de 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2955,7 +2955,8 @@ typedef enum cp_lvalue_kind { 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_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. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 72173fe..59722ac 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -100,11 +100,12 @@ lvalue_p_1 (tree ref, 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))) + 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. */ @@ -112,6 +113,9 @@ lvalue_p_1 (tree ref, /* 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: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 25fd059..646613a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2003-07-22 Nathan Sidwell <nathan@codesourcery.com> + * g++.dg/ext/packed3.C: New test. + * g++.dg/ext/packed4.C: New test. + * gcc.dg/pack-test-3.c: New test. 2003-07-21 Janis Johnson <janis187@us.ibm.com> diff --git a/gcc/testsuite/g++.dg/ext/packed3.C b/gcc/testsuite/g++.dg/ext/packed3.C new file mode 100644 index 0000000..b6e891f --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/packed3.C @@ -0,0 +1,25 @@ +// { 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" "" } +} diff --git a/gcc/testsuite/g++.dg/ext/packed4.C b/gcc/testsuite/g++.dg/ext/packed4.C new file mode 100644 index 0000000..c32a0fa --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/packed4.C @@ -0,0 +1,80 @@ +// { 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); +} |