diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2020-03-11 11:29:39 +0100 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2020-03-11 11:34:25 +0100 |
commit | e835226bab5b3575c8a55c048dcfed3d4cde5e0e (patch) | |
tree | efcc98ba6b3e9d24a8a1dd7176d1657a083e30bd /gcc/tree.c | |
parent | a5aac267e64c578d55e6e269fa9e331f0d01da98 (diff) | |
download | gcc-e835226bab5b3575c8a55c048dcfed3d4cde5e0e.zip gcc-e835226bab5b3575c8a55c048dcfed3d4cde5e0e.tar.gz gcc-e835226bab5b3575c8a55c048dcfed3d4cde5e0e.tar.bz2 |
Fix GIMPLE verification failure in LTO mode on Ada code
The issue is that tree_is_indexable doesn't return the same result for
a FIELD_DECL with QUAL_UNION_TYPE and the QUAL_UNION_TYPE, resulting
in two instances of the QUAL_UNION_TYPE in the bytecode. The result
for the type is the correct one (false, since it is variably modified)
while the result for the field is falsely true because:
else if (TREE_CODE (t) == FIELD_DECL
&& lto_variably_modified_type_p (DECL_CONTEXT (t)))
return false;
is not satisfied. The reason for this is that the DECL_QUALIFIER of
fields of a QUAL_UNION_TYPE depends on a discriminant in Ada, which
means that the size of the type does too (CONTAINS_PLACEHOLDER_P),
which in turn means that it is reset to a mere PLACEHOLDER_EXPR by
free_lang_data, which finally means that the size of DECL_CONTEXT is
too, so RETURN_TRUE_IF_VAR is false.
In other words, the CONTAINS_PLACEHOLDER_P property of the DECL_QUALIFIER
of fields of a QUAL_UNION_TYPE hides the variably_modified_type_p property
of these fields, if you look from the outside.
PR middle-end/93961
* tree.c (variably_modified_type_p) <RECORD_TYPE>: Recurse into
fields whose type is a qualified union.
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 10 |
1 files changed, 10 insertions, 0 deletions
@@ -9206,8 +9206,18 @@ variably_modified_type_p (tree type, tree fn) RETURN_TRUE_IF_VAR (DECL_SIZE (t)); RETURN_TRUE_IF_VAR (DECL_SIZE_UNIT (t)); + /* If the type is a qualified union, then the DECL_QUALIFIER + of fields can also be an expression containing a variable. */ if (TREE_CODE (type) == QUAL_UNION_TYPE) RETURN_TRUE_IF_VAR (DECL_QUALIFIER (t)); + + /* If the field is a qualified union, then it's only a container + for what's inside so we look into it. That's necessary in LTO + mode because the sizes of the field tested above have been set + to PLACEHOLDER_EXPRs by free_lang_data. */ + if (TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE + && variably_modified_type_p (TREE_TYPE (t), fn)) + return true; } break; |