aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2020-01-07 08:13:50 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2020-01-07 08:13:50 +0100
commitf74f6092ace420bd8a4498697754b06fc6da63bd (patch)
treecca42358fa3b5c25e78f163588388996a048c043 /gcc/cp
parent6ac22177a085e0ba36c95e71cee8235cc8b12947 (diff)
downloadgcc-f74f6092ace420bd8a4498697754b06fc6da63bd.zip
gcc-f74f6092ace420bd8a4498697754b06fc6da63bd.tar.gz
gcc-f74f6092ace420bd8a4498697754b06fc6da63bd.tar.bz2
re PR c++/91369 (Implement P0784R7: constexpr new)
PR c++/91369 * constexpr.c (struct constexpr_global_ctx): Add heap_alloc_count member, initialize it to zero in ctor. (cxx_eval_call_expression): Bump heap_dealloc_count when deleting a heap object. Don't cache calls to functions which allocate some heap objects and don't deallocate them or deallocate some heap objects they didn't allocate. * g++.dg/cpp1y/constexpr-new.C: Expect an error explaining why static_assert failed for C++2a. * g++.dg/cpp2a/constexpr-new9.C: New test. From-SVN: r279943
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/constexpr.c38
2 files changed, 46 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index abcbba5..77c7b10 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2020-01-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/91369
+ * constexpr.c (struct constexpr_global_ctx): Add heap_alloc_count
+ member, initialize it to zero in ctor.
+ (cxx_eval_call_expression): Bump heap_dealloc_count when deleting
+ a heap object. Don't cache calls to functions which allocate some
+ heap objects and don't deallocate them or deallocate some heap
+ objects they didn't allocate.
+
2020-01-06 Jason Merrill <jason@redhat.com>
PR c++/92552 - ICE with inherited constrained default ctor.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index c8852bd..417af18 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1041,8 +1041,11 @@ struct constexpr_global_ctx {
auto_vec<tree, 16> heap_vars;
/* Cleanups that need to be evaluated at the end of CLEANUP_POINT_EXPR. */
vec<tree> *cleanups;
+ /* Number of heap VAR_DECL deallocations. */
+ unsigned heap_dealloc_count;
/* Constructor. */
- constexpr_global_ctx () : constexpr_ops_count (0), cleanups (NULL) {}
+ constexpr_global_ctx ()
+ : constexpr_ops_count (0), cleanups (NULL), heap_dealloc_count (0) {}
};
/* The constexpr expansion context. CALL is the current function
@@ -2056,6 +2059,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
{
DECL_NAME (var) = heap_deleted_identifier;
ctx->global->values.remove (var);
+ ctx->global->heap_dealloc_count++;
return void_node;
}
else if (DECL_NAME (var) == heap_deleted_identifier)
@@ -2281,6 +2285,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
}
else
{
+ bool cacheable = true;
if (result && result != error_mark_node)
/* OK */;
else if (!DECL_SAVED_TREE (fun))
@@ -2346,6 +2351,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
auto_vec<tree, 10> save_exprs;
ctx_with_save_exprs.save_exprs = &save_exprs;
ctx_with_save_exprs.call = &new_call;
+ unsigned save_heap_alloc_count = ctx->global->heap_vars.length ();
+ unsigned save_heap_dealloc_count = ctx->global->heap_dealloc_count;
tree jump_target = NULL_TREE;
cxx_eval_constant_expression (&ctx_with_save_exprs, body,
@@ -2417,6 +2424,33 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
/* Make the unshared function copy we used available for re-use. */
save_fundef_copy (fun, copy);
+
+ /* If the call allocated some heap object that hasn't been
+ deallocated during the call, or if it deallocated some heap
+ object it has not allocated, the call isn't really stateless
+ for the constexpr evaluation and should not be cached.
+ It is fine if the call allocates something and deallocates it
+ too. */
+ if (entry
+ && (save_heap_alloc_count != ctx->global->heap_vars.length ()
+ || (save_heap_dealloc_count
+ != ctx->global->heap_dealloc_count)))
+ {
+ tree heap_var;
+ unsigned int i;
+ if ((ctx->global->heap_vars.length ()
+ - ctx->global->heap_dealloc_count)
+ != save_heap_alloc_count - save_heap_dealloc_count)
+ cacheable = false;
+ else
+ FOR_EACH_VEC_ELT_FROM (ctx->global->heap_vars, i, heap_var,
+ save_heap_alloc_count)
+ if (DECL_NAME (heap_var) != heap_deleted_identifier)
+ {
+ cacheable = false;
+ break;
+ }
+ }
}
if (result == error_mark_node)
@@ -2426,7 +2460,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
else if (!result)
result = void_node;
if (entry)
- entry->result = result;
+ entry->result = cacheable ? result : error_mark_node;
}
/* The result of a constexpr function must be completely initialized.