diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2008-05-13 08:46:18 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2008-05-13 08:46:18 +0000 |
commit | f80cddcb5d45179f285da0a56a36db694935148d (patch) | |
tree | d5e33cde32652206851dc8984dcaa621347d97ff /gcc/ada/utils.c | |
parent | 8beaca66e37f300d7ca91beae79c0f4eb341f760 (diff) | |
download | gcc-f80cddcb5d45179f285da0a56a36db694935148d.zip gcc-f80cddcb5d45179f285da0a56a36db694935148d.tar.gz gcc-f80cddcb5d45179f285da0a56a36db694935148d.tar.bz2 |
re PR ada/24880 (infinite loop on conversion of integer type with size clause)
PR ada/24880
PR ada/26635
* utils.c (convert) <INTEGER_TYPE>: When converting an additive
expression to an integral type with lower precision, use NOP_EXPR
directly in a couple of special cases.
From-SVN: r135257
Diffstat (limited to 'gcc/ada/utils.c')
-rw-r--r-- | gcc/ada/utils.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c index 202818d..b4b3894 100644 --- a/gcc/ada/utils.c +++ b/gcc/ada/utils.c @@ -3627,7 +3627,7 @@ convert (tree type, tree expr) if (TYPE_FAT_POINTER_P (type) && !TYPE_FAT_POINTER_P (etype)) return convert_to_fat_pointer (type, expr); - /* If we're converting between two aggregate types that are mere + /* If we are converting between two aggregate types that are mere variants, just make a VIEW_CONVERT_EXPR. */ else if (code == ecode && AGGREGATE_TYPE_P (type) @@ -3662,6 +3662,30 @@ convert (tree type, tree expr) /* ... fall through ... */ case ENUMERAL_TYPE: + /* If we are converting an additive expression to an integer type + with lower precision, be wary of the optimization that can be + applied by convert_to_integer. There are 2 problematic cases: + - if the first operand was originally of a biased type, + because we could be recursively called to convert it + to an intermediate type and thus rematerialize the + additive operator endlessly, + - if the expression contains a placeholder, because an + intermediate conversion that changes the sign could + be inserted and thus introduce an artificial overflow + at compile time when the placeholder is substituted. */ + if (code == INTEGER_TYPE + && ecode == INTEGER_TYPE + && TYPE_PRECISION (type) < TYPE_PRECISION (etype) + && (TREE_CODE (expr) == PLUS_EXPR || TREE_CODE (expr) == MINUS_EXPR)) + { + tree op0 = get_unwidened (TREE_OPERAND (expr, 0), type); + + if ((TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE + && TYPE_BIASED_REPRESENTATION_P (TREE_TYPE (op0))) + || CONTAINS_PLACEHOLDER_P (expr)) + return build1 (NOP_EXPR, type, expr); + } + return fold (convert_to_integer (type, expr)); case POINTER_TYPE: |