aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/utils.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2021-02-03 11:38:04 +0100
committerEric Botcazou <ebotcazou@adacore.com>2021-02-03 11:38:04 +0100
commite8c87bc07b5c98101b47caaee84650cd8abdfa5f (patch)
tree5badee4ab77820205d39dd2344f571f358af2fe2 /gcc/ada/gcc-interface/utils.c
parentfc130ab54fd9a254f07426f9c180c367b039d7f9 (diff)
downloadgcc-e8c87bc07b5c98101b47caaee84650cd8abdfa5f.zip
gcc-e8c87bc07b5c98101b47caaee84650cd8abdfa5f.tar.gz
gcc-e8c87bc07b5c98101b47caaee84650cd8abdfa5f.tar.bz2
Fix regression with partial rep clause on variant record type
It can yield an incorrect layout when there is a partial representation clause on a discriminated record type with a variant part. gcc/ada/ * gcc-interface/decl.c (components_to_record): If the first component with rep clause is the _Parent field with variable size, temporarily set it aside when computing the internal layout of the REP part again. * gcc-interface/utils.c (finish_record_type): Revert to taking the maximum when merging sizes for all record types with rep clause. (merge_sizes): Put SPECIAL parameter last and adjust recursive calls.
Diffstat (limited to 'gcc/ada/gcc-interface/utils.c')
-rw-r--r--gcc/ada/gcc-interface/utils.c39
1 files changed, 20 insertions, 19 deletions
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 2656f11..952f032 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -2051,7 +2051,6 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
this_ada_size = this_size;
const bool variant_part = (TREE_CODE (type) == QUAL_UNION_TYPE);
- const bool variant_part_at_zero = variant_part && integer_zerop (pos);
/* Clear DECL_BIT_FIELD for the cases layout_decl does not handle. */
if (DECL_BIT_FIELD (field)
@@ -2094,7 +2093,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
/* Clear DECL_BIT_FIELD_TYPE for a variant part at offset 0, it's simply
not supported by the DECL_BIT_FIELD_REPRESENTATIVE machinery because
the variant part is always the last field in the list. */
- if (variant_part_at_zero)
+ if (variant_part && integer_zerop (pos))
DECL_BIT_FIELD_TYPE (field) = NULL_TREE;
/* If we still have DECL_BIT_FIELD set at this point, we know that the
@@ -2129,18 +2128,20 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
case RECORD_TYPE:
/* Since we know here that all fields are sorted in order of
increasing bit position, the size of the record is one
- higher than the ending bit of the last field processed,
- unless we have a variant part at offset 0, since in this
- case we might have a field outside the variant part that
- has a higher ending position; so use a MAX in this case.
- Also, if this field is a QUAL_UNION_TYPE, we need to take
- into account the previous size in the case of empty variants. */
+ higher than the ending bit of the last field processed
+ unless we have a rep clause, because we might be processing
+ the REP part of a record with a variant part for which the
+ variant part has a rep clause but not the fixed part, in
+ which case this REP part may contain overlapping fields
+ and thus needs to be treated like a union tyoe above, so
+ use a MAX in that case. Also, if this field is a variant
+ part, we need to take into account the previous size in
+ the case of empty variants. */
ada_size
- = merge_sizes (ada_size, pos, this_ada_size, variant_part,
- variant_part_at_zero);
+ = merge_sizes (ada_size, pos, this_ada_size, rep_level > 0,
+ variant_part);
size
- = merge_sizes (size, pos, this_size, variant_part,
- variant_part_at_zero);
+ = merge_sizes (size, pos, this_size, rep_level > 0, variant_part);
break;
default:
@@ -2432,14 +2433,14 @@ rest_of_record_type_compilation (tree record_type)
}
/* Utility function of above to merge LAST_SIZE, the previous size of a record
- with FIRST_BIT and SIZE that describe a field. SPECIAL is true if this
- represents a QUAL_UNION_TYPE in which case we must look for COND_EXPRs and
- replace a value of zero with the old size. If MAX is true, we take the
+ with FIRST_BIT and SIZE that describe a field. If MAX is true, we take the
MAX of the end position of this field with LAST_SIZE. In all other cases,
- we use FIRST_BIT plus SIZE. Return an expression for the size. */
+ we use FIRST_BIT plus SIZE. SPECIAL is true if it's for a QUAL_UNION_TYPE,
+ in which case we must look for COND_EXPRs and replace a value of zero with
+ the old size. Return an expression for the size. */
static tree
-merge_sizes (tree last_size, tree first_bit, tree size, bool special, bool max)
+merge_sizes (tree last_size, tree first_bit, tree size, bool max, bool special)
{
tree type = TREE_TYPE (last_size);
tree new_size;
@@ -2456,11 +2457,11 @@ merge_sizes (tree last_size, tree first_bit, tree size, bool special, bool max)
integer_zerop (TREE_OPERAND (size, 1))
? last_size : merge_sizes (last_size, first_bit,
TREE_OPERAND (size, 1),
- 1, max),
+ max, special),
integer_zerop (TREE_OPERAND (size, 2))
? last_size : merge_sizes (last_size, first_bit,
TREE_OPERAND (size, 2),
- 1, max));
+ max, special));
/* We don't need any NON_VALUE_EXPRs and they can confuse us (especially
when fed through SUBSTITUTE_IN_EXPR) into thinking that a constant