aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2021-11-24 05:45:02 -0500
committerJason Merrill <jason@redhat.com>2021-12-01 13:24:36 -0500
commit53caa4723d8de73fe21e63ba264082f3071b2887 (patch)
tree594eeeda07a0ebd5559f79ed4c469c544cbf3637 /gcc/fold-const.c
parentd683a1b3e89007211a7c800bb61647d8ac42cb6b (diff)
downloadgcc-53caa4723d8de73fe21e63ba264082f3071b2887.zip
gcc-53caa4723d8de73fe21e63ba264082f3071b2887.tar.gz
gcc-53caa4723d8de73fe21e63ba264082f3071b2887.tar.bz2
c++: constexpr, fold, weak redecl, fp/0 [PR103310]
For PR61825, honza changed tree_single_nonzero_warnv_p to prevent a later declaration from marking a function as weak after we've determined that it wasn't weak before. But we shouldn't do that for speculative folding; we should only do it when we actually need a constant value. In C++, such a context is called "manifestly constant-evaluated". In fold, this seems to correspond to the folding_initializer flag, since in C this situation only occurs in static initializers. This change makes nonzero-1.c well-formed; I've added a nonzero-1a.c to verify that we delete the null check eventually if there is no weak redeclaration. The varasm.c change is so that if we do get the weak redeclaration error, we get it at the position of the weak declaration rather than the previous declaration. Using the FOLD_INIT paths also affects floating point arithmetic: notably, this makes floating point division by zero in a manifestly constant-evaluated context constant, as in a C static initializer. I've had some success convincing CWG that this is the right direction; C++ should follow C's floating point semantics more than we have been doing, and Joseph says that the C policy is that Annex F overrides other parts of the standard that say that some operations are undefined. But since we're in stage 3, I'm only making this change with the new flag -fconstexpr-fp-except. It may turn on by default in a future release. I think this distinction is only relevant for binary operations; arithmetic for the floating point case, comparison for possibly non-zero addresses. PR c++/103310 gcc/ChangeLog: * fold-const.c (maybe_nonzero_address): Use get_create or get depending on folding_initializer. (fold_binary_initializer_loc): New. * fold-const.h (fold_binary_initializer_loc): Declare. * varasm.c (mark_weak): Don't use the decl location. * doc/invoke.texi: Document -fconstexpr-fp-except. gcc/c-family/ChangeLog: * c.opt: Add -fconstexpr-fp-except. gcc/cp/ChangeLog: * constexpr.c (cxx_eval_binary_expression): Use fold_binary_initializer_loc if manifestly cxeval. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-fp-except1.C: New test. * g++.dg/cpp1z/constexpr-if36.C: New test. * gcc.dg/tree-ssa/nonzero-1.c: Now well-formed. * gcc.dg/tree-ssa/nonzero-1a.c: New test.
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 90d8225..0b9a42f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -85,8 +85,8 @@ along with GCC; see the file COPYING3. If not see
#include "asan.h"
#include "gimple-range.h"
-/* Nonzero if we are folding constants inside an initializer; zero
- otherwise. */
+/* Nonzero if we are folding constants inside an initializer or a C++
+ manifestly-constant-evaluated context; zero otherwise. */
int folding_initializer = 0;
/* The following constants represent a bit based encoding of GCC's
@@ -9924,8 +9924,15 @@ pointer_may_wrap_p (tree base, tree offset, poly_int64 bitpos)
static int
maybe_nonzero_address (tree decl)
{
+ /* Normally, don't do anything for variables and functions before symtab is
+ built; it is quite possible that DECL will be declared weak later.
+ But if folding_initializer, we need a constant answer now, so create
+ the symtab entry and prevent later weak declaration. */
if (DECL_P (decl) && decl_in_symtab_p (decl))
- if (struct symtab_node *symbol = symtab_node::get_create (decl))
+ if (struct symtab_node *symbol
+ = (folding_initializer
+ ? symtab_node::get_create (decl)
+ : symtab_node::get (decl)))
return symbol->nonzero_address ();
/* Function local objects are never NULL. */
@@ -13991,6 +13998,19 @@ fold_build_call_array_initializer_loc (location_t loc, tree type, tree fn,
return result;
}
+tree
+fold_binary_initializer_loc (location_t loc, tree_code code, tree type,
+ tree lhs, tree rhs)
+{
+ tree result;
+ START_FOLD_INIT;
+
+ result = fold_binary_loc (loc, code, type, lhs, rhs);
+
+ END_FOLD_INIT;
+ return result;
+}
+
#undef START_FOLD_INIT
#undef END_FOLD_INIT