Commit e1ac6e5b by Olivier Hainque Committed by Arnaud Charlet

cuintp.c (UI_To_gnu): Use a proper type for intermediate computations to ensure…

cuintp.c (UI_To_gnu): Use a proper type for intermediate computations to ensure bias adjustments take...

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.

From-SVN: r106963
parent 2368f04e
......@@ -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--)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment