diff options
author | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-15 13:54:14 +0000 |
---|---|---|
committer | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-15 13:54:14 +0000 |
commit | 8820a966cecaf84bbf63cdafa3e616239e7a1fbd (patch) | |
tree | 86a95cdf244ee0c5fda1fa480d98b5c92f52d9c9 /gcc/ada/cuintp.c | |
parent | 2c3d0a6d737c0b55769f8e2169bc210b85575f72 (diff) | |
download | gcc-8820a966cecaf84bbf63cdafa3e616239e7a1fbd.tar.gz |
2005-11-14 Olivier Hainque <hainque@adacore.com>
* cuintp.c (UI_To_gnu): Use a proper type for intermediate computations
to ensure bias adjustments take place when need be and to prevent
occurrences of intermediate overflows.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@106963 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/cuintp.c')
-rw-r--r-- | gcc/ada/cuintp.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/gcc/ada/cuintp.c b/gcc/ada/cuintp.c index ff2dfb9027b..7adc057ce7c 100644 --- a/gcc/ada/cuintp.c +++ b/gcc/ada/cuintp.c @@ -6,7 +6,7 @@ * * * C Implementation File * * * - * Copyright (C) 1992-2003 Free Software Foundation, Inc. * + * Copyright (C) 1992-2005 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- * @@ -41,6 +41,7 @@ #include "stringt.h" #include "fe.h" #include "gigi.h" +#include "ada-tree.h" /* Universal integers are represented by the Uint type which is an index into the Uints_Ptr table containing Uint_Entry values. A Uint_Entry contains an @@ -74,22 +75,41 @@ UI_To_gnu (Uint Input, tree type) { tree gnu_ret; + /* We might have a TYPE with biased representation and be passed an + unbiased value that doesn't fit. We always use an unbiased type able + to hold any such possible value for intermediate computations, and + then rely on a conversion back to TYPE to perform the bias adjustment + when need be. */ + + int biased_type_p + = (TREE_CODE (type) == INTEGER_TYPE + && TYPE_BIASED_REPRESENTATION_P (type)); + + tree comp_type = biased_type_p ? get_base_type (type) : type; + if (Input <= Uint_Direct_Last) - gnu_ret = build_cst_from_int (type, Input - Uint_Direct_Bias); + gnu_ret = build_cst_from_int (comp_type, Input - Uint_Direct_Bias); else { Int Idx = Uints_Ptr[Input].Loc; Pos Length = Uints_Ptr[Input].Length; Int First = Udigits_Ptr[Idx]; - /* Do computations in integer type or TYPE whichever is wider, then - convert later. This avoid overflow if type is short integer. */ - tree comp_type - = ((TREE_CODE (type) == REAL_TYPE - || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node)) - ? type : integer_type_node); - tree gnu_base = build_cst_from_int (comp_type, Base); + tree gnu_base; gcc_assert (Length > 0); + + /* The computations we perform below always require a type at least as + large as an integer not to overflow. REAL types are always fine, but + INTEGER or ENUMERAL types we are handed may be too short. We use a + base integer type node for the computations in this case and will + convert the final result back to the incoming type later on. */ + + if (TREE_CODE (comp_type) != REAL_TYPE + && TYPE_PRECISION (comp_type) < TYPE_PRECISION (integer_type_node)) + comp_type = integer_type_node; + + gnu_base = build_cst_from_int (comp_type, Base); + gnu_ret = build_cst_from_int (comp_type, First); if (First < 0) for (Idx++, Length--; Length; Idx++, Length--) |