Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< --
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; some 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. --- gcc/cp/constexpr.cc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index c6f323ebf43..9d85c3be5cc 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)) { base-commit: caabf0973a4e9a26421c94d540e3e20051e93e77 -- 2.39.3