diff options
Diffstat (limited to 'gcc/c-lex.c')
-rw-r--r-- | gcc/c-lex.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/gcc/c-lex.c b/gcc/c-lex.c index 5b71c3b0d8f..72a959052d2 100644 --- a/gcc/c-lex.c +++ b/gcc/c-lex.c @@ -605,8 +605,10 @@ static tree interpret_float (const cpp_token *token, unsigned int flags) { tree type; + tree const_type; tree value; REAL_VALUE_TYPE real; + REAL_VALUE_TYPE real_trunc; char *copy; size_t copylen; @@ -655,6 +657,10 @@ interpret_float (const cpp_token *token, unsigned int flags) else type = double_type_node; + const_type = excess_precision_type (type); + if (!const_type) + const_type = type; + /* Copy the constant to a nul-terminated buffer. If the constant has any suffixes, cut them off; REAL_VALUE_ATOF/ REAL_VALUE_HTOF can't handle them. */ @@ -675,13 +681,21 @@ interpret_float (const cpp_token *token, unsigned int flags) memcpy (copy, token->val.str.text, copylen); copy[copylen] = '\0'; - real_from_string3 (&real, copy, TYPE_MODE (type)); + real_from_string3 (&real, copy, TYPE_MODE (const_type)); + if (const_type != type) + /* Diagnosing if the result of converting the value with excess + precision to the semantic type would overflow (with associated + double rounding) is more appropriate than diagnosing if the + result of converting the string directly to the semantic type + would overflow. */ + real_convert (&real_trunc, TYPE_MODE (type), &real); /* Both C and C++ require a diagnostic for a floating constant outside the range of representable values of its type. Since we have __builtin_inf* to produce an infinity, this is now a mandatory pedwarn if the target does not support infinities. */ - if (REAL_VALUE_ISINF (real)) + if (REAL_VALUE_ISINF (real) + || (const_type != type && REAL_VALUE_ISINF (real_trunc))) { if (!MODE_HAS_INFINITIES (TYPE_MODE (type))) pedwarn (input_location, 0, "floating constant exceeds range of %qT", type); @@ -689,7 +703,8 @@ interpret_float (const cpp_token *token, unsigned int flags) warning (OPT_Woverflow, "floating constant exceeds range of %qT", type); } /* We also give a warning if the value underflows. */ - else if (REAL_VALUES_EQUAL (real, dconst0)) + else if (REAL_VALUES_EQUAL (real, dconst0) + || (const_type != type && REAL_VALUES_EQUAL (real_trunc, dconst0))) { REAL_VALUE_TYPE realvoidmode; int overflow = real_from_string (&realvoidmode, copy); @@ -698,9 +713,13 @@ interpret_float (const cpp_token *token, unsigned int flags) } /* Create a node with determined type and value. */ - value = build_real (type, real); + value = build_real (const_type, real); if (flags & CPP_N_IMAGINARY) - value = build_complex (NULL_TREE, convert (type, integer_zero_node), value); + value = build_complex (NULL_TREE, convert (const_type, integer_zero_node), + value); + + if (type != const_type) + value = build1 (EXCESS_PRECISION_EXPR, type, value); return value; } |