diff options
Diffstat (limited to 'gcc/c-typeck.c')
-rw-r--r-- | gcc/c-typeck.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 7e98384ce28..58694cb5ceb 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -281,14 +281,30 @@ composite_type (tree t1, tree t2) tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); int quals; tree unqual_elt; + tree d1 = TYPE_DOMAIN (t1); + tree d2 = TYPE_DOMAIN (t2); + bool d1_variable, d2_variable; + bool d1_zero, d2_zero; /* We should not have any type quals on arrays at all. */ gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2)); + d1_zero = d1 == 0 || !TYPE_MAX_VALUE (d1); + d2_zero = d2 == 0 || !TYPE_MAX_VALUE (d2); + + d1_variable = (!d1_zero + && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST + || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST)); + d2_variable = (!d2_zero + && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST + || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); + /* Save space: see if the result is identical to one of the args. */ - if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)) + if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1) + && (d2_variable || d2_zero || !d1_variable)) return build_type_attribute_variant (t1, attributes); - if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)) + if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2) + && (d1_variable || d1_zero || !d2_variable)) return build_type_attribute_variant (t2, attributes); if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) @@ -304,7 +320,12 @@ composite_type (tree t1, tree t2) quals = TYPE_QUALS (strip_array_types (elt)); unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED); t1 = build_array_type (unqual_elt, - TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); + TYPE_DOMAIN ((TYPE_DOMAIN (t1) + && (d2_variable + || d2_zero + || !d1_variable)) + ? t1 + : t2)); t1 = c_build_qualified_type (t1, quals); return build_type_attribute_variant (t1, attributes); } |