diff options
author | Jason Merrill <jason@redhat.com> | 2023-07-13 17:48:05 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2023-07-17 17:19:30 -0400 |
commit | c7ac1de5f5c561b2d90c084a638c232d322d54e6 (patch) | |
tree | d5b323908cf927886e5536cbcd58ccae0dc1224a /gcc/cp/constexpr.cc | |
parent | c5e9927b95debc692374a2aede21856eb94217ae (diff) | |
download | gcc-c7ac1de5f5c561b2d90c084a638c232d322d54e6.zip gcc-c7ac1de5f5c561b2d90c084a638c232d322d54e6.tar.gz gcc-c7ac1de5f5c561b2d90c084a638c232d322d54e6.tar.bz2 |
c++: only cache constexpr calls that are constant exprs
In reviewing Nathaniel's patch for PR70331, it occurred to me that instead
of looking for various specific problematic things in the result of a
constexpr call to decide whether to cache it, we should use
reduced_constant_expression_p.
The change to that function is to avoid crashing on uninitialized objects of
non-class type.
In a trial version of this patch I checked to see what cases this stopped
caching; most were instances of partially-initialized return values, which
seem fine to not cache. Some were returning pointers to expiring local
variables, which we definitely want not to cache. And one was bit-cast3.C,
which will be handled in a follow-up patch.
gcc/cp/ChangeLog:
* constexpr.cc (cxx_eval_call_expression): Only cache
reduced_constant_expression_p results.
(reduced_constant_expression_p): Handle CONSTRUCTOR of scalar type.
(cxx_eval_constant_expression): Fold vectors here.
(cxx_eval_bare_aggregate): Not here.
Diffstat (limited to 'gcc/cp/constexpr.cc')
-rw-r--r-- | gcc/cp/constexpr.cc | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index c6f323e..9d85c3b 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -3033,7 +3033,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, } else { - bool cacheable = true; + bool cacheable = !!entry; if (result && result != error_mark_node) /* OK */; else if (!DECL_SAVED_TREE (fun)) @@ -3185,7 +3185,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, for the constexpr evaluation and should not be cached. It is fine if the call allocates something and deallocates it too. */ - if (entry + if (cacheable && (save_heap_alloc_count != ctx->global->heap_vars.length () || (save_heap_dealloc_count != ctx->global->heap_dealloc_count))) @@ -3204,10 +3204,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, cacheable = false; break; } - /* Also don't cache a call that returns a deallocated pointer. */ - if (cacheable && (cp_walk_tree_without_duplicates - (&result, find_heap_var_refs, NULL))) - cacheable = false; } /* Rewrite all occurrences of the function's RESULT_DECL with the @@ -3217,6 +3213,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, && !is_empty_class (TREE_TYPE (res))) if (replace_decl (&result, res, ctx->object)) cacheable = false; + + /* Only cache a permitted result of a constant expression. */ + if (cacheable && !reduced_constant_expression_p (result)) + cacheable = false; } else /* Couldn't get a function copy to evaluate. */ @@ -3268,8 +3268,9 @@ reduced_constant_expression_p (tree t) case CONSTRUCTOR: /* And we need to handle PTRMEM_CST wrapped in a CONSTRUCTOR. */ tree field; - if (TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE) - /* An initialized vector would have a VECTOR_CST. */ + if (!AGGREGATE_TYPE_P (TREE_TYPE (t))) + /* A constant vector would be folded to VECTOR_CST. + A CONSTRUCTOR of scalar type means uninitialized. */ return false; if (CONSTRUCTOR_NO_CLEARING (t)) { |