Commit 54c7a7f3 by Nick Clifton Committed by Nick Clifton

re PR middle-end/28865 (Structures with a flexible arrray member have wrong .size)

PR middle-end/28865

	* varasm.c (output_constant): Return the number of bytes actually
	emitted.
	(output_constructor_array_range): Update the field size with the
	number of bytes emitted by output_constant.
	(output_constructor_regular_field): Likewise.  Also do not
 	complain if the total number of bytes emitted is now greater
	than the expected fieldpos.
	* output.h (output_constant): Update prototype and descriptive
	comment.

	* gcc.c-torture/compile/pr28865.c: New.
	* gcc.c-torture/execute/pr28865.c: New.

From-SVN: r206661
parent 5147d10a
2014-01-16 Nick Clifton <nickc@redhat.com>
PR middle-end/28865
* varasm.c (output_constant): Return the number of bytes actually
emitted.
(output_constructor_array_range): Update the field size with the
number of bytes emitted by output_constant.
(output_constructor_regular_field): Likewise. Also do not
complain if the total number of bytes emitted is now greater
than the expected fieldpos.
* output.h (output_constant): Update prototype and descriptive
comment.
2014-01-16 Marek Polacek <polacek@redhat.com>
PR middle-end/59827
......
......@@ -294,11 +294,13 @@ extern void output_quoted_string (FILE *, const char *);
This includes the pseudo-op such as ".int" or ".byte", and a newline.
Assumes output_addressed_constants has been done on EXP already.
Generate exactly SIZE bytes of assembler data, padding at the end
with zeros if necessary. SIZE must always be specified.
Generate at least SIZE bytes of assembler data, padding at the end
with zeros if necessary. SIZE must always be specified. The returned
value is the actual number of bytes of assembler data generated, which
may be bigger than SIZE if the object contains a variable length field.
ALIGN is the alignment in bits that may be assumed for the data. */
extern void output_constant (tree, unsigned HOST_WIDE_INT, unsigned int);
extern unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT, unsigned int);
/* When outputting delayed branch sequences, this rtx holds the
sequence being output. It is null when no delayed branch
......
2014-01-16 Nick Clifton <nickc@redhat.com>
PR middle-end/28865
* gcc.c-torture/compile/pr28865.c: New.
* gcc.c-torture/execute/pr28865.c: New.
2014-01-16 Marek Polacek <polacek@redhat.com>
PR middle-end/59827
......
struct var_len
{
int field1;
const char field2[];
};
/* Note - strictly speaking this array declaration is illegal
since each element has a variable length. GCC allows it
(for the moment) because it is used in existing code, such
as glibc. */
static const struct var_len var_array[] =
{
{ 1, "Long exposure noise reduction" },
{ 2, "Shutter/AE lock buttons" },
{ 3, "Mirror lockup" }
};
struct A { int a; char b[]; };
union B { struct A a; char b[sizeof (struct A) + 31]; };
union B b = { { 1, "123456789012345678901234567890" } };
union B c = { { 2, "123456789012345678901234567890" } };
__attribute__((noinline, noclone)) void
foo (int *x[2])
{
x[0] = &b.a.a;
x[1] = &c.a.a;
}
int
main ()
{
int *x[2];
foo (x);
if (*x[0] != 1 || *x[1] != 2)
__builtin_abort ();
return 0;
}
......@@ -4584,8 +4584,10 @@ static unsigned HOST_WIDE_INT
This includes the pseudo-op such as ".int" or ".byte", and a newline.
Assumes output_addressed_constants has been done on EXP already.
Generate exactly SIZE bytes of assembler data, padding at the end
with zeros if necessary. SIZE must always be specified.
Generate at least SIZE bytes of assembler data, padding at the end
with zeros if necessary. SIZE must always be specified. The returned
value is the actual number of bytes of assembler data generated, which
may be bigger than SIZE if the object contains a variable length field.
SIZE is important for structure constructors,
since trailing members may have been omitted from the constructor.
......@@ -4600,14 +4602,14 @@ static unsigned HOST_WIDE_INT
ALIGN is the alignment of the data in bits. */
void
unsigned HOST_WIDE_INT
output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
{
enum tree_code code;
unsigned HOST_WIDE_INT thissize;
if (size == 0 || flag_syntax_only)
return;
return size;
/* See if we're trying to initialize a pointer in a non-default mode
to the address of some declaration somewhere. If the target says
......@@ -4672,7 +4674,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
&& vec_safe_is_empty (CONSTRUCTOR_ELTS (exp)))
{
assemble_zeros (size);
return;
return size;
}
if (TREE_CODE (exp) == FDESC_EXPR)
......@@ -4684,7 +4686,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
#else
gcc_unreachable ();
#endif
return;
return size;
}
/* Now output the underlying data. If we've handling the padding, return.
......@@ -4723,8 +4725,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
switch (TREE_CODE (exp))
{
case CONSTRUCTOR:
output_constructor (exp, size, align, NULL);
return;
return output_constructor (exp, size, align, NULL);
case STRING_CST:
thissize
= MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size);
......@@ -4752,11 +4753,10 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
case RECORD_TYPE:
case UNION_TYPE:
gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
output_constructor (exp, size, align, NULL);
return;
return output_constructor (exp, size, align, NULL);
case ERROR_MARK:
return;
return 0;
default:
gcc_unreachable ();
......@@ -4764,6 +4764,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
if (size > thissize)
assemble_zeros (size - thissize);
return size;
}
......@@ -4860,7 +4862,7 @@ output_constructor_array_range (oc_local_state *local)
if (local->val == NULL_TREE)
assemble_zeros (fieldsize);
else
output_constant (local->val, fieldsize, align2);
fieldsize = output_constant (local->val, fieldsize, align2);
/* Count its size. */
local->total_bytes += fieldsize;
......@@ -4909,9 +4911,8 @@ output_constructor_regular_field (oc_local_state *local)
Note no alignment needed in an array, since that is guaranteed
if each element has the proper size. */
if ((local->field != NULL_TREE || local->index != NULL_TREE)
&& fieldpos != local->total_bytes)
&& fieldpos > local->total_bytes)
{
gcc_assert (fieldpos >= local->total_bytes);
assemble_zeros (fieldpos - local->total_bytes);
local->total_bytes = fieldpos;
}
......@@ -4948,7 +4949,7 @@ output_constructor_regular_field (oc_local_state *local)
if (local->val == NULL_TREE)
assemble_zeros (fieldsize);
else
output_constant (local->val, fieldsize, align2);
fieldsize = output_constant (local->val, fieldsize, align2);
/* Count its size. */
local->total_bytes += fieldsize;
......
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