Commit 1937f939 by Jason Merrill Committed by Jason Merrill

re PR c++/13983 (no warning on some non-POD struct with packed attribute)

        PR c++/13983
        PR c++/17519
        * stor-layout.c (finish_record_layout): Copy TYPE_PACKED to variants.
        * c-common.c (handle_packed_attribute): So don't copy it here.
        * c-decl.c (finish_struct): Don't copy TYPE_ALIGN.
        * cp/class.c (check_field_decls): Check TYPE_PACKED after
        stripping array types.
        (finish_struct_bits): Don't copy TYPE_SIZE here.

From-SVN: r115217
parent 562349ca
2006-07-05 Jason Merrill <jason@redhat.com>
PR c++/13983
PR c++/17519
* stor-layout.c (finish_record_layout): Copy TYPE_PACKED to variants.
* c-common.c (handle_packed_attribute): So don't copy it here.
* c-decl.c (finish_struct): Don't copy TYPE_ALIGN.
2006-07-05 Mike Stump <mrs@apple.com>
* doc/invoke.texi (Invoking G++): Clarify prose for g++.
......
......@@ -4082,20 +4082,6 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
*node = build_variant_type_copy (*node);
TYPE_PACKED (*node) = 1;
if (TYPE_MAIN_VARIANT (*node) == *node)
{
/* If it is the main variant, then pack the other variants
too. This happens in,
struct Foo {
struct Foo const *ptr; // creates a variant w/o packed flag
} __ attribute__((packed)); // packs it now.
*/
tree probe;
for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe))
TYPE_PACKED (probe) = 1;
}
}
else if (TREE_CODE (*node) == FIELD_DECL)
{
......
......@@ -5574,8 +5574,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
{
TYPE_FIELDS (x) = TYPE_FIELDS (t);
TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
TYPE_ALIGN (x) = TYPE_ALIGN (t);
TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (t);
C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t);
C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t);
C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
......
2006-07-05 Jason Merrill <jason@redhat.com>
PR c++/13983
PR c++/17519
* class.c (check_field_decls): Check TYPE_PACKED after
stripping array types.
(finish_struct_bits): Don't copy TYPE_SIZE here.
PR c++/18681
* friend.c (is_friend): Fix DR 45 implementation.
......
......@@ -1433,8 +1433,6 @@ finish_struct_bits (tree t)
TYPE_VFIELD (variants) = TYPE_VFIELD (t);
TYPE_METHODS (variants) = TYPE_METHODS (t);
TYPE_FIELDS (variants) = TYPE_FIELDS (t);
TYPE_SIZE (variants) = TYPE_SIZE (t);
TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t);
}
if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) && TYPE_POLYMORPHIC_P (t))
......@@ -2815,40 +2813,6 @@ check_field_decls (tree t, tree *access_decls,
next = &TREE_CHAIN (x);
if (TREE_CODE (x) == FIELD_DECL)
{
if (TYPE_PACKED (t))
{
if (!pod_type_p (TREE_TYPE (x)) && !TYPE_PACKED (TREE_TYPE (x)))
warning
(0,
"ignoring packed attribute on unpacked non-POD field %q+#D",
x);
else if (TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
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
non-empty. */
;
else
{
tree element_type;
/* The class is non-empty. */
CLASSTYPE_EMPTY_P (t) = 0;
/* The class is not even nearly empty. */
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* If one of the data members contains an empty class,
so does T. */
element_type = strip_array_types (type);
if (CLASS_TYPE_P (element_type)
&& CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type))
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
}
}
if (TREE_CODE (x) == USING_DECL)
{
/* Prune the access declaration from the list of fields. */
......@@ -2945,6 +2909,34 @@ check_field_decls (tree t, tree *access_decls,
type = strip_array_types (type);
if (TYPE_PACKED (t))
{
if (!pod_type_p (type) && !TYPE_PACKED (type))
warning
(0,
"ignoring packed attribute on unpacked non-POD field %q+#D",
x);
else if (TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
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
non-empty. */
;
else
{
/* The class is non-empty. */
CLASSTYPE_EMPTY_P (t) = 0;
/* The class is not even nearly empty. */
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* If one of the data members contains an empty class,
so does T. */
if (CLASS_TYPE_P (type)
&& CLASSTYPE_CONTAINS_EMPTY_CLASS_P (type))
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
}
/* This is used by -Weffc++ (see below). Warn only for pointers
to members which might hold dynamic memory. So do not warn
for pointers to functions or pointers to members. */
......
......@@ -1465,6 +1465,8 @@ finalize_type_size (tree type)
void
finish_record_layout (record_layout_info rli, int free_p)
{
tree variant;
/* Compute the final size. */
finalize_record_size (rli);
......@@ -1474,6 +1476,12 @@ finish_record_layout (record_layout_info rli, int free_p)
/* Perform any last tweaks to the TYPE_SIZE, etc. */
finalize_type_size (rli->t);
/* Propagate TYPE_PACKED to variants. With C++ templates,
handle_packed_attribute is too early to do this. */
for (variant = TYPE_NEXT_VARIANT (rli->t); variant;
variant = TYPE_NEXT_VARIANT (variant))
TYPE_PACKED (variant) = TYPE_PACKED (rli->t);
/* Lay out any static members. This is done now because their type
may use the record's type. */
while (rli->pending_statics)
......
// PR c++/13983, c++/17519
// The typedef and the array were causing us to miss that A<int> is
// a packed type.
template <class T>
struct A {
A();
} __attribute__((packed));
typedef A<int> Ai;
struct B {
Ai a[2];
} __attribute__((packed));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment