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

Reply via email to