summaryrefslogtreecommitdiff
path: root/gcc/ada/cuintp.c
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2005-11-15 13:54:14 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2005-11-15 13:54:14 +0000
commit8820a966cecaf84bbf63cdafa3e616239e7a1fbd (patch)
tree86a95cdf244ee0c5fda1fa480d98b5c92f52d9c9 /gcc/ada/cuintp.c
parent2c3d0a6d737c0b55769f8e2169bc210b85575f72 (diff)
downloadgcc-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.c38
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--)