aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2014-01-16 12:17:48 +0000
committerNick Clifton <nickc@gcc.gnu.org>2014-01-16 12:17:48 +0000
commit54c7a7f3b07b2198ecd84cdab579ec41057389f9 (patch)
treef86b15eb863f6a929fad7d545aa4f7c28340eaa0 /gcc/varasm.c
parent5147d10aa4b2b608a02fb885a5510c983e148f06 (diff)
downloadgcc-54c7a7f3b07b2198ecd84cdab579ec41057389f9.zip
gcc-54c7a7f3b07b2198ecd84cdab579ec41057389f9.tar.gz
gcc-54c7a7f3b07b2198ecd84cdab579ec41057389f9.tar.bz2
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
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c31
1 files changed, 16 insertions, 15 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 24b36b6..6a41644 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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;