diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2010-07-22 19:28:21 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2010-07-22 19:28:21 +0000 |
commit | 980a05010bfa731a05dc11e44ce4126f6b6021f2 (patch) | |
tree | 7b449669820919931ac175790046520c1ccf6b51 /gcc/ada/gcc-interface/utils.c | |
parent | cfa0bd19c5187edf728c1ca985b1c8ee7a477c73 (diff) | |
download | gcc-980a05010bfa731a05dc11e44ce4126f6b6021f2.zip gcc-980a05010bfa731a05dc11e44ce4126f6b6021f2.tar.gz gcc-980a05010bfa731a05dc11e44ce4126f6b6021f2.tar.bz2 |
re PR ada/44892 (internal error on gnat.dg/unchecked_convert5.adb)
PR ada/44892
* gcc-interface/utils.c (convert): Fix thinko in test.
(unchecked_convert): When converting from a scalar type to a type with
a different size, pad to have the same size on both sides.
From-SVN: r162425
Diffstat (limited to 'gcc/ada/gcc-interface/utils.c')
-rw-r--r-- | gcc/ada/gcc-interface/utils.c | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index eb65b7d..541f7bb 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -3702,9 +3702,10 @@ convert (tree type, tree expr) if (ecode == RECORD_TYPE && CONTAINS_PLACEHOLDER_P (DECL_SIZE (TYPE_FIELDS (type)))) { - if (TREE_CONSTANT (TYPE_SIZE (etype))) + if (TREE_CODE (TYPE_SIZE (etype)) == INTEGER_CST) expr = convert (maybe_pad_type (etype, TYPE_SIZE (type), 0, Empty, - false, false, false, true), expr); + false, false, false, true), + expr); return unchecked_convert (type, expr, false); } @@ -4353,6 +4354,7 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) tree etype = TREE_TYPE (expr); enum tree_code ecode = TREE_CODE (etype); enum tree_code code = TREE_CODE (type); + int c; /* If the expression is already of the right type, we are done. */ if (etype == type) @@ -4393,7 +4395,8 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) /* If we are converting to an integral type whose precision is not equal to its size, first unchecked convert to a record that contains an object of the output type. Then extract the field. */ - else if (INTEGRAL_TYPE_P (type) && TYPE_RM_SIZE (type) + else if (INTEGRAL_TYPE_P (type) + && TYPE_RM_SIZE (type) && 0 != compare_tree_int (TYPE_RM_SIZE (type), GET_MODE_BITSIZE (TYPE_MODE (type)))) { @@ -4410,9 +4413,10 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) /* Similarly if we are converting from an integral type whose precision is not equal to its size. */ - else if (INTEGRAL_TYPE_P (etype) && TYPE_RM_SIZE (etype) - && 0 != compare_tree_int (TYPE_RM_SIZE (etype), - GET_MODE_BITSIZE (TYPE_MODE (etype)))) + else if (INTEGRAL_TYPE_P (etype) + && TYPE_RM_SIZE (etype) + && 0 != compare_tree_int (TYPE_RM_SIZE (etype), + GET_MODE_BITSIZE (TYPE_MODE (etype)))) { tree rec_type = make_node (RECORD_TYPE); tree field = create_field_decl (get_identifier ("OBJ"), etype, rec_type, @@ -4427,6 +4431,38 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) expr = unchecked_convert (type, expr, notrunc_p); } + /* If we are converting from a scalar type to a type with a different size, + we need to pad to have the same size on both sides. + + ??? We cannot do it unconditionally because unchecked conversions are + used liberally by the front-end to implement polymorphism, e.g. in: + + S191s : constant ada__tags__addr_ptr := ada__tags__addr_ptr!(S190s); + return p___size__4 (p__object!(S191s.all)); + + so we skip all expressions that are references. */ + else if (!REFERENCE_CLASS_P (expr) + && !AGGREGATE_TYPE_P (etype) + && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST + && (c = tree_int_cst_compare (TYPE_SIZE (etype), TYPE_SIZE (type)))) + { + if (c < 0) + { + expr = convert (maybe_pad_type (etype, TYPE_SIZE (type), 0, Empty, + false, false, false, true), + expr); + expr = unchecked_convert (type, expr, notrunc_p); + } + else + { + tree rec_type = maybe_pad_type (type, TYPE_SIZE (etype), 0, Empty, + false, false, false, true); + expr = unchecked_convert (rec_type, expr, notrunc_p); + expr = build_component_ref (expr, NULL_TREE, TYPE_FIELDS (rec_type), + false); + } + } + /* We have a special case when we are converting between two unconstrained array types. In that case, take the address, convert the fat pointer types, and dereference. */ |