diff options
author | jsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-03-30 01:50:44 +0000 |
---|---|---|
committer | jsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-03-30 01:50:44 +0000 |
commit | c6418a4e44bad350f57aac0ce1d0f6ce6c6a1c9f (patch) | |
tree | 07c0a2aef08a00219e11f34b2e1a27c0dd432823 /gcc/c-lex.c | |
parent | 7666d572f2a547f09f39811c7af07f9532251a02 (diff) | |
download | gcc-c6418a4e44bad350f57aac0ce1d0f6ce6c6a1c9f.tar.gz |
PR rtl-optimization/323
* c-common.c (c_fully_fold, convert_and_check,
c_common_truthvalue_conversion): Handle EXCESS_PRECISION_EXPR.
(c_fully_fold_internal): Disallow EXCESS_PRECISION_EXPR.
* c-common.def (EXCESS_PRECISION_EXPR): New.
* c-cppbuiltin.c (builtin_define_float_constants): Define
constants with enough digits for long double.
* c-lex.c (interpret_float): Interpret constant with excess
precision where appropriate.
* c-opts.c (c_common_post_options): Set
flag_excess_precision_cmdline. Give an error for
-fexcess-precision=standard for C++ for processors where the
option is significant.
* c-parser.c (c_parser_conditional_expression): Handle excess
precision in condition.
* c-typeck.c (convert_arguments): Handle arguments with excess
precision.
(build_unary_op): Move excess precision outside operation.
(build_conditional_expr): Likewise.
(build_compound_expr): Likewise.
(build_c_cast): Do cast on operand of EXCESS_PRECISION_EXPR.
(build_modify_expr): Handle excess precision in RHS.
(convert_for_assignment): Handle excess precision in converted
value.
(digest_init, output_init_element, process_init_element): Handle
excess precision in initializer.
(c_finish_return): Handle excess precision in return value.
(build_binary_op): Handle excess precision in operands and add
excess precision as needed for operation.
* common.opt (-fexcess-precision=): New option.
* config/i386/i386.h (X87_ENABLE_ARITH, X87_ENABLE_FLOAT): New.
* config/i386/i386.md (float<SSEMODEI24:mode><X87MODEF:mode>2):
For standard excess precision, output explicit conversion to and
truncation from XFmode.
(*float<SSEMODEI24:mode><X87MODEF:mode>2_1,
*float<SSEMODEI24:mode><X87MODEF:mode>2_i387_with_temp,
*float<SSEMODEI24:mode><X87MODEF:mode>2_i387, two unnamed
define_splits, floatdi<X87MODEF:mode>2_i387_with_xmm, two unnamed
define_splits, *floatunssi<mode>2_1, two unnamed define_splits,
floatunssi<mode>2, add<mode>3, sub<mode>3, mul<mode>3, divdf3,
divsf3, *fop_<mode>_comm_i387, *fop_<mode>_1_i387,
*fop_<MODEF:mode>_2_i387, *fop_<MODEF:mode>_3_i387,
*fop_df_4_i387, *fop_df_5_i387, *fop_df_6_i387, two unnamed
define_splits, sqrt<mode>2): Disable where appropriate for
standard excess precision.
* convert.c (convert_to_real): Do not shorten arithmetic to type
for which excess precision would be used.
* defaults.h (TARGET_FLT_EVAL_METHOD_NON_DEFAULT): Define.
* doc/invoke.texi (-fexcess-precision=): Document option.
(-mfpmath=): Correct index entry.
* flags.h (enum excess_precision, flag_excess_precision_cmdline,
flag_excess_precision): New.
* langhooks.c (lhd_post_options): Set
flag_excess_precision_cmdline.
* opts.c (common_handle_option): Handle -fexcess-precision=.
* toplev.c (flag_excess_precision_cmdline, flag_excess_precision,
init_excess_precision): New.
(lang_dependent_init_target): Call init_excess_precision.
* tree.c (excess_precision_type): New.
* tree.h (excess_precision_type): Declare.
ada:
* gcc-interface/misc.c (gnat_post_options): Set
flag_excess_precision_cmdline. Give an error for
-fexcess-precision=standard for processors where the option is
significant.
fortran:
* options.c (gfc_post_options): Set
flag_excess_precision_cmdline. Give an error for
-fexcess-precision=standard for processors where the option is
significant.
java:
* lang.c (java_post_options): Set flag_excess_precision_cmdline.
Give an error for -fexcess-precision=standard for processors where
the option is significant.
testsuite:
* gcc.target/i386/excess-precision-1.c,
gcc.target/i386/excess-precision-2.c,
gcc.target/i386/excess-precision-3.c,
gcc.target/i386/excess-precision-4.c,
gcc.target/i386/excess-precision-5.c,
gcc.target/i386/excess-precision-6.c: New tests.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145272 138bc75d-0d04-0410-961f-82ee72b054a4
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; } |