]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: only cache constexpr calls that are constant exprs
authorJason Merrill <jason@redhat.com>
Thu, 13 Jul 2023 21:48:05 +0000 (17:48 -0400)
committerJason Merrill <jason@redhat.com>
Mon, 17 Jul 2023 21:19:30 +0000 (17:19 -0400)
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.

gcc/cp/constexpr.cc

index c6f323ebf43a8cb0a6ab6c9398c18f5b36bfa3e5..9d85c3be5cc9b498aed0a0689cae6008225f4344 100644 (file)
@@ -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))
        {