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> 2014-01-16 Marek Polacek <polacek@redhat.com>
PR middle-end/59827 PR middle-end/59827
......
...@@ -294,11 +294,13 @@ extern void output_quoted_string (FILE *, const char *); ...@@ -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. This includes the pseudo-op such as ".int" or ".byte", and a newline.
Assumes output_addressed_constants has been done on EXP already. Assumes output_addressed_constants has been done on EXP already.
Generate exactly SIZE bytes of assembler data, padding at the end Generate at least SIZE bytes of assembler data, padding at the end
with zeros if necessary. SIZE must always be specified. 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. */ 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 /* When outputting delayed branch sequences, this rtx holds the
sequence being output. It is null when no delayed branch 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> 2014-01-16 Marek Polacek <polacek@redhat.com>
PR middle-end/59827 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 ...@@ -4584,8 +4584,10 @@ static unsigned HOST_WIDE_INT
This includes the pseudo-op such as ".int" or ".byte", and a newline. This includes the pseudo-op such as ".int" or ".byte", and a newline.
Assumes output_addressed_constants has been done on EXP already. Assumes output_addressed_constants has been done on EXP already.
Generate exactly SIZE bytes of assembler data, padding at the end Generate at least SIZE bytes of assembler data, padding at the end
with zeros if necessary. SIZE must always be specified. 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, SIZE is important for structure constructors,
since trailing members may have been omitted from the constructor. since trailing members may have been omitted from the constructor.
...@@ -4600,14 +4602,14 @@ static unsigned HOST_WIDE_INT ...@@ -4600,14 +4602,14 @@ static unsigned HOST_WIDE_INT
ALIGN is the alignment of the data in bits. */ 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) output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
{ {
enum tree_code code; enum tree_code code;
unsigned HOST_WIDE_INT thissize; unsigned HOST_WIDE_INT thissize;
if (size == 0 || flag_syntax_only) if (size == 0 || flag_syntax_only)
return; return size;
/* See if we're trying to initialize a pointer in a non-default mode /* 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 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) ...@@ -4672,7 +4674,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
&& vec_safe_is_empty (CONSTRUCTOR_ELTS (exp))) && vec_safe_is_empty (CONSTRUCTOR_ELTS (exp)))
{ {
assemble_zeros (size); assemble_zeros (size);
return; return size;
} }
if (TREE_CODE (exp) == FDESC_EXPR) if (TREE_CODE (exp) == FDESC_EXPR)
...@@ -4684,7 +4686,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) ...@@ -4684,7 +4686,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
#else #else
gcc_unreachable (); gcc_unreachable ();
#endif #endif
return; return size;
} }
/* Now output the underlying data. If we've handling the padding, return. /* 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) ...@@ -4723,8 +4725,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
switch (TREE_CODE (exp)) switch (TREE_CODE (exp))
{ {
case CONSTRUCTOR: case CONSTRUCTOR:
output_constructor (exp, size, align, NULL); return output_constructor (exp, size, align, NULL);
return;
case STRING_CST: case STRING_CST:
thissize thissize
= MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size); = 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) ...@@ -4752,11 +4753,10 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
case RECORD_TYPE: case RECORD_TYPE:
case UNION_TYPE: case UNION_TYPE:
gcc_assert (TREE_CODE (exp) == CONSTRUCTOR); gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
output_constructor (exp, size, align, NULL); return output_constructor (exp, size, align, NULL);
return;
case ERROR_MARK: case ERROR_MARK:
return; return 0;
default: default:
gcc_unreachable (); gcc_unreachable ();
...@@ -4764,6 +4764,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) ...@@ -4764,6 +4764,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
if (size > thissize) if (size > thissize)
assemble_zeros (size - thissize); assemble_zeros (size - thissize);
return size;
} }
...@@ -4860,7 +4862,7 @@ output_constructor_array_range (oc_local_state *local) ...@@ -4860,7 +4862,7 @@ output_constructor_array_range (oc_local_state *local)
if (local->val == NULL_TREE) if (local->val == NULL_TREE)
assemble_zeros (fieldsize); assemble_zeros (fieldsize);
else else
output_constant (local->val, fieldsize, align2); fieldsize = output_constant (local->val, fieldsize, align2);
/* Count its size. */ /* Count its size. */
local->total_bytes += fieldsize; local->total_bytes += fieldsize;
...@@ -4909,9 +4911,8 @@ output_constructor_regular_field (oc_local_state *local) ...@@ -4909,9 +4911,8 @@ output_constructor_regular_field (oc_local_state *local)
Note no alignment needed in an array, since that is guaranteed Note no alignment needed in an array, since that is guaranteed
if each element has the proper size. */ if each element has the proper size. */
if ((local->field != NULL_TREE || local->index != NULL_TREE) 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); assemble_zeros (fieldpos - local->total_bytes);
local->total_bytes = fieldpos; local->total_bytes = fieldpos;
} }
...@@ -4948,7 +4949,7 @@ output_constructor_regular_field (oc_local_state *local) ...@@ -4948,7 +4949,7 @@ output_constructor_regular_field (oc_local_state *local)
if (local->val == NULL_TREE) if (local->val == NULL_TREE)
assemble_zeros (fieldsize); assemble_zeros (fieldsize);
else else
output_constant (local->val, fieldsize, align2); fieldsize = output_constant (local->val, fieldsize, align2);
/* Count its size. */ /* Count its size. */
local->total_bytes += fieldsize; 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