aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/misc.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2017-02-24 10:00:04 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2017-02-24 10:00:04 +0000
commitbf6b72928e7a8d1734e14ef075dc9c985a4902fe (patch)
treee5293e4d0a31ed5753df85e0cae454a18c38ed30 /gcc/ada/gcc-interface/misc.c
parent4af362a9571170538b66411d9cf7b6dc87745854 (diff)
downloadgcc-bf6b72928e7a8d1734e14ef075dc9c985a4902fe.zip
gcc-bf6b72928e7a8d1734e14ef075dc9c985a4902fe.tar.gz
gcc-bf6b72928e7a8d1734e14ef075dc9c985a4902fe.tar.bz2
misc.c (gnat_type_max_size): Try to return a meaningful value for array types with TYPE_INDEX_TYPE set on...
* gcc-interface/misc.c (gnat_type_max_size): Try to return a meaningful value for array types with TYPE_INDEX_TYPE set on their domain type. * gcc-interface/utils.c (max_size): For operations and expressions, do not build a new node if the operands have not changed or are missing. From-SVN: r245698
Diffstat (limited to 'gcc/ada/gcc-interface/misc.c')
-rw-r--r--gcc/ada/gcc-interface/misc.c69
1 files changed, 53 insertions, 16 deletions
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 1fed72a..cdabfec 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
- * Copyright (C) 1992-2016, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2017, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -736,22 +736,59 @@ gnat_type_max_size (const_tree gnu_type)
elaborated and possibly replaced by a VAR_DECL. */
tree max_unitsize = max_size (TYPE_SIZE_UNIT (gnu_type), true);
- /* If we don't have a constant, see what we can get from TYPE_ADA_SIZE,
- which should stay untouched. */
- if (!tree_fits_uhwi_p (max_unitsize)
- && RECORD_OR_UNION_TYPE_P (gnu_type)
- && !TYPE_FAT_POINTER_P (gnu_type)
- && TYPE_ADA_SIZE (gnu_type))
+ /* If we don't have a constant, try to look at attributes which should have
+ stayed untouched. */
+ if (!tree_fits_uhwi_p (max_unitsize))
{
- tree max_adasize = max_size (TYPE_ADA_SIZE (gnu_type), true);
-
- /* If we have succeeded in finding a constant, round it up to the
- type's alignment and return the result in units. */
- if (tree_fits_uhwi_p (max_adasize))
- max_unitsize
- = size_binop (CEIL_DIV_EXPR,
- round_up (max_adasize, TYPE_ALIGN (gnu_type)),
- bitsize_unit_node);
+ /* For record types, see what we can get from TYPE_ADA_SIZE. */
+ if (RECORD_OR_UNION_TYPE_P (gnu_type)
+ && !TYPE_FAT_POINTER_P (gnu_type)
+ && TYPE_ADA_SIZE (gnu_type))
+ {
+ tree max_adasize = max_size (TYPE_ADA_SIZE (gnu_type), true);
+
+ /* If we have succeeded in finding a constant, round it up to the
+ type's alignment and return the result in units. */
+ if (tree_fits_uhwi_p (max_adasize))
+ max_unitsize
+ = size_binop (CEIL_DIV_EXPR,
+ round_up (max_adasize, TYPE_ALIGN (gnu_type)),
+ bitsize_unit_node);
+ }
+
+ /* For array types, see what we can get from TYPE_INDEX_TYPE. */
+ else if (TREE_CODE (gnu_type) == ARRAY_TYPE
+ && TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type))
+ && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (gnu_type))))
+ {
+ tree lb = TYPE_MIN_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)));
+ tree hb = TYPE_MAX_VALUE (TYPE_INDEX_TYPE (TYPE_DOMAIN (gnu_type)));
+ if (TREE_CODE (lb) != INTEGER_CST
+ && TYPE_RM_SIZE (TREE_TYPE (lb))
+ && compare_tree_int (TYPE_RM_SIZE (TREE_TYPE (lb)), 16) <= 0)
+ lb = TYPE_MIN_VALUE (TREE_TYPE (lb));
+ if (TREE_CODE (hb) != INTEGER_CST
+ && TYPE_RM_SIZE (TREE_TYPE (hb))
+ && compare_tree_int (TYPE_RM_SIZE (TREE_TYPE (hb)), 16) <= 0)
+ hb = TYPE_MAX_VALUE (TREE_TYPE (hb));
+ if (TREE_CODE (lb) == INTEGER_CST && TREE_CODE (hb) == INTEGER_CST)
+ {
+ tree ctype = get_base_type (TREE_TYPE (lb));
+ lb = fold_convert (ctype, lb);
+ hb = fold_convert (ctype, hb);
+ if (tree_int_cst_le (lb, hb))
+ {
+ tree length
+ = fold_build2 (PLUS_EXPR, ctype,
+ fold_build2 (MINUS_EXPR, ctype, hb, lb),
+ build_int_cst (ctype, 1));
+ max_unitsize
+ = fold_build2 (MULT_EXPR, sizetype,
+ fold_convert (sizetype, length),
+ TYPE_SIZE_UNIT (TREE_TYPE (gnu_type)));
+ }
+ }
+ }
}
return max_unitsize;