aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/call.c24
-rw-r--r--gcc/cp/class.c10
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/tree.c14
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/ext/packed3.C25
-rw-r--r--gcc/testsuite/g++.dg/ext/packed4.C80
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);
+}