diff options
author | Patrick Palka <ppalka@redhat.com> | 2020-05-21 09:03:43 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2020-05-21 09:03:43 -0400 |
commit | f65a3299a521a44522c1e01724f75e36af22f40b (patch) | |
tree | 5b3d9e479413cd1aef174c8929ed8cf8f5936c28 /gcc/cp/cp-tree.h | |
parent | 5855bdfa06fb25c0880af89cb2bfdcdf342beac2 (diff) | |
download | gcc-f65a3299a521a44522c1e01724f75e36af22f40b.zip gcc-f65a3299a521a44522c1e01724f75e36af22f40b.tar.gz gcc-f65a3299a521a44522c1e01724f75e36af22f40b.tar.bz2 |
c++: template instantiation during fold_for_warn [PR94038]
Unfortunately, the previous fix to PR94038 is fragile. When the
argument to fold_for_warn is a bare CALL_EXPR, then all is well: the
result of maybe_constant_value from fold_for_warn (with
uid_sensitive=true) is reused via the cv_cache in the subsequent call to
maybe_constant_value from cp_fold (with uid_sensitive=false), so we
avoid instantiating bar<int>.
But when the argument to fold_for_warn is more complex, e.g. an
INDIRECT_REF of a CALL_EXPR, as in the testcase below (due to bar<int>()
returning const int& which we need to decay to int) then from
fold_for_warn we call maybe_constant_value on the INDIRECT_REF, and from
cp_fold we call it on the CALL_EXPR, so there is no reuse via the
cv_cache and we therefore end up instantiating bar<int>.
So for a more robust solution to this general issue of warning flags
affecting code generation, it seems that we need a way to globally avoid
template instantiation during constexpr evaluation whenever we're
performing warning-dependent folding.
To that end, this patch replaces the flag constexpr_ctx::uid_sensitive
with a global flag uid_sensitive_constexpr_evaluation_p, and enables it
during fold_for_warn using an RAII helper.
The patch also adds a counter that keeps track of the number of times
uid_sensitive_constexpr_evaluation_p is called and returned true, and we
use this to determine whether the result of constexpr evaluation
was restricted by the flag. This lets us safely update the cv_cache and
fold_cache from fold_for_warn in the most common case where the flag
did not restrict constexpr evaluation.
gcc/cp/ChangeLog:
PR c++/94038
* constexpr.c (constexpr_ctx::uid_sensitive): Remove field.
(uid_sensitive_constexpr_evaluation_value): Define.
(uid_sensitive_constexpr_evaluation_true_counter): Define.
(uid_sensitive_constexpr_evaluation_p): Define.
(uid_sensitive_constexpr_evaluation_sentinel): Define its
constructor.
(uid_sensitive_constexpr_evaluation_checker): Define its
constructor and its evaluation_restricted_p method.
(get_fundef_copy): Remove 'ctx' parameter. Use u_s_c_e_p
instead of constexpr_ctx::uid_sensitive.
(cxx_eval_call_expression): Use u_s_c_e_p instead, and test it
last. Adjust call to get_fundef_copy.
(instantiate_cx_fn_r): Test u_s_c_e_p so that we increment the
counter if necessary.
(cxx_eval_outermost_constant_expr): Remove 'uid_sensitive'
parameter. Adjust function body accordingly.
(maybe_constant_value): Remove 'uid_sensitive' parameter and
adjust function body accordingly. Set up a
uid_sensitive_constexpr_evaluation_checker, and use it to
conditionally update the cv_cache.
* cp-gimplify.c (cp_fold): Set up a
uid_sensitive_constexpr_evaluation_checker, and use it to
conditionally update the fold_cache.
* cp-tree.h (maybe_constant_value): Update declaration.
(struct uid_sensitive_constexpr_evaluation_sentinel): Define.
(struct sensitive_constexpr_evaluation_checker): Define.
* expr.c (fold_for_warn): Set up a
uid_sensitive_constexpr_evaluation_sentinel before calling
the folding subroutines. Drop all but the first argument to
maybe_constant_value.
gcc/testsuite/ChangeLog:
PR c++/94038
* g++.dg/warn/pr94038-2.C: New test.
Diffstat (limited to 'gcc/cp/cp-tree.h')
-rw-r--r-- | gcc/cp/cp-tree.h | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 27707ab..07c1614 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7950,7 +7950,7 @@ extern bool require_potential_rvalue_constant_expression (tree); extern tree cxx_constant_value (tree, tree = NULL_TREE); extern void cxx_constant_dtor (tree, tree); extern tree cxx_constant_init (tree, tree = NULL_TREE); -extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false, bool = false); +extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false); extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false); extern tree fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error, @@ -7969,6 +7969,27 @@ extern tree fold_sizeof_expr (tree); extern void clear_cv_and_fold_caches (bool = true); extern tree unshare_constructor (tree CXX_MEM_STAT_INFO); +/* An RAII sentinel used to restrict constexpr evaluation so that it + doesn't do anything that causes extra DECL_UID generation. */ + +struct uid_sensitive_constexpr_evaluation_sentinel +{ + temp_override<bool> ovr; + uid_sensitive_constexpr_evaluation_sentinel (); +}; + +/* Used to determine whether uid_sensitive_constexpr_evaluation_p was + called and returned true, indicating that we've restricted constexpr + evaluation in order to avoid UID generation. We use this to control + updates to the fold_cache and cv_cache. */ + +struct uid_sensitive_constexpr_evaluation_checker +{ + const unsigned saved_counter; + uid_sensitive_constexpr_evaluation_checker (); + bool evaluation_restricted_p () const; +}; + /* In cp-ubsan.c */ extern void cp_ubsan_maybe_instrument_member_call (tree); extern void cp_ubsan_instrument_member_accesses (tree *); |