aboutsummaryrefslogtreecommitdiff
path: root/gcc/doc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-10-14 09:28:57 +0200
committerJakub Jelinek <jakub@redhat.com>2022-10-14 09:28:57 +0200
commit98e341130f87984af07c884fea773c0bb3cc8821 (patch)
tree2517b1b2ca58af9d2c34a5aaa25ea3e3cc568366 /gcc/doc
parent18981635127c6701733dc052aa054e569271b733 (diff)
downloadgcc-98e341130f87984af07c884fea773c0bb3cc8821.zip
gcc-98e341130f87984af07c884fea773c0bb3cc8821.tar.gz
gcc-98e341130f87984af07c884fea773c0bb3cc8821.tar.bz2
c++: Implement excess precision support for C++ [PR107097, PR323]
The following patch implements excess precision support for C++. Like for C, it uses EXCESS_PRECISION_EXPR tree to say that its operand is evaluated in excess precision and what the semantic type of the expression is. In most places I've followed what the C FE does in similar spots, so e.g. for binary ops if one or both operands are already EXCESS_PRECISION_EXPR, strip those away or for operations that might need excess precision (+, -, *, /) check if the operands should use excess precision and convert to that type and at the end wrap into EXCESS_PRECISION_EXPR with the common semantic type. This patch follows the C99 handling where it differs from C11 handling. There are some cases which needed to be handled differently, the C FE can just strip EXCESS_PRECISION_EXPR (replace it with its operand) when handling explicit cast, but that IMHO isn't right for C++ - the discovery what exact conversion should be used (e.g. if user conversion or standard or their sequence) should be decided based on the semantic type (i.e. type of EXCESS_PRECISION_EXPR), and that decision continues in convert_like* where we pick the right user conversion, again, if say some class has ctor from double and long double and we are on ia32 with standard excess precision promoting float/double to long double, then we should pick the ctor from double. Or when some other class has ctor from just double, and EXCESS_PRECISION_EXPR semantic type is float, we should choose the user ctor from double, but actually just convert the long double excess precision to double and not to float first. We need to make sure even identity conversion converts from excess precision to the semantic one though, but if identity is chained with other conversions, we don't want the identity next_conversion to drop to semantic precision only to widen afterwards. The existing testcases tweaks were for cases on i686-linux where excess precision breaks those tests, e.g. if we have double d = 4.2; if (d == 4.2) then it does the expected thing only with -fexcess-precision=fast, because with -fexcess-precision=standard it is actually double d = 4.2; if ((long double) d == 4.2L) where 4.2L is different from 4.2. I've added -fexcess-precision=fast to some tests and changed other tests to use constants that are exactly representable and don't suffer from these excess precision issues. There is one exception, pr68180.C looks like a bug in the patch which is also present in the C FE (so I'd like to get it resolved incrementally in both). Reduced testcase: typedef float __attribute__((vector_size (16))) float32x4_t; float32x4_t foo(float32x4_t x, float y) { return x + y; } with -m32 -std=c11 -Wno-psabi or -m32 -std=c++17 -Wno-psabi it is rejected with: pr68180.c:2:52: error: conversion of scalar ‘long double’ to vector ‘float32x4_t’ {aka ‘__vector(4) float’} involves truncation but without excess precision (say just -std=c11 -Wno-psabi or -std=c++17 -Wno-psabi) it is accepted. Perhaps we should pass down the semantic type to scalar_to_vector and use the semantic type rather than excess precision type in the diagnostics. 2022-10-14 Jakub Jelinek <jakub@redhat.com> PR middle-end/323 PR c++/107097 gcc/ * doc/invoke.texi (-fexcess-precision=standard): Mention that the option now also works in C++. gcc/c-family/ * c-common.def (EXCESS_PRECISION_EXPR): Remove comment part about the tree being specific to C/ObjC. * c-opts.cc (c_common_post_options): Handle flag_excess_precision in C++ the same as in C. * c-lex.cc (interpret_float): Set const_type to excess_precision () even for C++. gcc/cp/ * parser.cc (cp_parser_primary_expression): Handle EXCESS_PRECISION_EXPR with REAL_CST operand the same as REAL_CST. * cvt.cc (cp_ep_convert_and_check): New function. * call.cc (build_conditional_expr): Add excess precision support. When type_after_usual_arithmetic_conversions returns error_mark_node, use gcc_checking_assert that it is because of uncomparable floating point ranks instead of checking all those conditions and make it work also with complex types. (convert_like_internal): Likewise. Add NESTED_P argument, pass true to recursive calls to convert_like. (convert_like): Add NESTED_P argument, pass it through to convert_like_internal. For other overload pass false to it. (convert_like_with_context): Pass false to NESTED_P. (convert_arg_to_ellipsis): Add excess precision support. (magic_varargs_p): For __builtin_is{finite,inf,inf_sign,nan,normal} and __builtin_fpclassify return 2 instead of 1, document what it means. (build_over_call): Don't handle former magic 2 which is no longer used, instead for magic 1 remove EXCESS_PRECISION_EXPR. (perform_direct_initialization_if_possible): Pass false to NESTED_P convert_like argument. * constexpr.cc (cxx_eval_constant_expression): Handle EXCESS_PRECISION_EXPR. (potential_constant_expression_1): Likewise. * pt.cc (tsubst_copy, tsubst_copy_and_build): Likewise. * cp-tree.h (cp_ep_convert_and_check): Declare. * cp-gimplify.cc (cp_fold): Handle EXCESS_PRECISION_EXPR. * typeck.cc (cp_common_type): For COMPLEX_TYPEs, return error_mark_node if recursive call returned it. (convert_arguments): For magic 1 remove EXCESS_PRECISION_EXPR. (cp_build_binary_op): Add excess precision support. When cp_common_type returns error_mark_node, use gcc_checking_assert that it is because of uncomparable floating point ranks instead of checking all those conditions and make it work also with complex types. (cp_build_unary_op): Likewise. (cp_build_compound_expr): Likewise. (build_static_cast_1): Remove EXCESS_PRECISION_EXPR. gcc/testsuite/ * gcc.target/i386/excess-precision-1.c: For C++ wrap abort and exit declarations into extern "C" block. * gcc.target/i386/excess-precision-2.c: Likewise. * gcc.target/i386/excess-precision-3.c: Likewise. Remove check_float_nonproto and check_double_nonproto tests for C++. * gcc.target/i386/excess-precision-7.c: For C++ wrap abort and exit declarations into extern "C" block. * gcc.target/i386/excess-precision-9.c: Likewise. * g++.target/i386/excess-precision-1.C: New test. * g++.target/i386/excess-precision-2.C: New test. * g++.target/i386/excess-precision-3.C: New test. * g++.target/i386/excess-precision-4.C: New test. * g++.target/i386/excess-precision-5.C: New test. * g++.target/i386/excess-precision-6.C: New test. * g++.target/i386/excess-precision-7.C: New test. * g++.target/i386/excess-precision-9.C: New test. * g++.target/i386/excess-precision-11.C: New test. * c-c++-common/dfp/convert-bfp-10.c: Add -fexcess-precision=fast as dg-additional-options. * c-c++-common/dfp/compare-eq-const.c: Likewise. * g++.dg/cpp1z/constexpr-96862.C: Likewise. * g++.dg/cpp1z/decomp12.C (main): Use 2.25 instead of 2.3 to avoid excess precision differences. * g++.dg/other/thunk1.C: Add -fexcess-precision=fast as dg-additional-options. * g++.dg/vect/pr64410.cc: Likewise. * g++.dg/cpp1y/pr68180.C: Likewise. * g++.dg/vect/pr89653.cc: Likewise. * g++.dg/cpp0x/variadic-tuple.C: Likewise. * g++.dg/cpp0x/nsdmi-union1.C: Use 4.25 instead of 4.2 to avoid excess precision differences. * g++.old-deja/g++.brendan/copy9.C: Add -fexcess-precision=fast as dg-additional-options. * g++.old-deja/g++.brendan/overload7.C: Likewise.
Diffstat (limited to 'gcc/doc')
-rw-r--r--gcc/doc/invoke.texi10
1 files changed, 5 insertions, 5 deletions
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index a9ecc44..c176e2d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13785,18 +13785,18 @@ default, @option{-fexcess-precision=fast} is in effect; this means that
operations may be carried out in a wider precision than the types specified
in the source if that would result in faster code, and it is unpredictable
when rounding to the types specified in the source code takes place.
-When compiling C, if @option{-fexcess-precision=standard} is specified then
-excess precision follows the rules specified in ISO C99; in particular,
+When compiling C or C++, if @option{-fexcess-precision=standard} is specified
+then excess precision follows the rules specified in ISO C99 or C++; in particular,
both casts and assignments cause values to be rounded to their
semantic types (whereas @option{-ffloat-store} only affects
-assignments). This option is enabled by default for C if a strict
-conformance option such as @option{-std=c99} is used.
+assignments). This option is enabled by default for C or C++ if a strict
+conformance option such as @option{-std=c99} or @option{-std=c++17} is used.
@option{-ffast-math} enables @option{-fexcess-precision=fast} by default
regardless of whether a strict conformance option is used.
@opindex mfpmath
@option{-fexcess-precision=standard} is not implemented for languages
-other than C. On the x86, it has no effect if @option{-mfpmath=sse}
+other than C or C++. On the x86, it has no effect if @option{-mfpmath=sse}
or @option{-mfpmath=sse+387} is specified; in the former case, IEEE
semantics apply without excess precision, and in the latter, rounding
is unpredictable.