diff options
author | Jakub Jelinek <jakub@redhat.com> | 2019-11-02 00:26:17 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-11-02 00:26:17 +0100 |
commit | 8412b939d1cf375c8e478e39a5ac9d7260e4c23c (patch) | |
tree | fa30aa009dcb3b40d9e2996606c4f8ec9635d72e /gcc/cp/constexpr.c | |
parent | 8a8ce49e0f3983e1b72f490a59ded92bca053c71 (diff) | |
download | gcc-8412b939d1cf375c8e478e39a5ac9d7260e4c23c.zip gcc-8412b939d1cf375c8e478e39a5ac9d7260e4c23c.tar.gz gcc-8412b939d1cf375c8e478e39a5ac9d7260e4c23c.tar.bz2 |
PR c++/91369 - Implement P0784R7: constexpr new
PR c++/91369 - Implement P0784R7: constexpr new
* cp-tree.h (CALL_FROM_NEW_OR_DELETE_P): Define.
* init.c (build_new_1, build_vec_delete_1, build_delete): Set
CALL_FROM_NEW_OR_DELETE_P on the CALL_EXPR to allocator functions.
* constexpr.c (is_std_allocator_allocate): Only allow
global replaceable allocator functions if CALL_FROM_NEW_OR_DELETE_P
or in std::allocate<T>::{,de}allocate.
(potential_constant_expression_1): Likewise.
* g++.dg/cpp2a/constexpr-new6.C: New test.
* g++.dg/cpp2a/constexpr-new7.C: New test.
From-SVN: r277732
Diffstat (limited to 'gcc/cp/constexpr.c')
-rw-r--r-- | gcc/cp/constexpr.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 75db0b3..4baaac0 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1638,6 +1638,28 @@ is_std_construct_at (tree fndecl) return name && id_equal (name, "construct_at"); } +/* Return true if FNDECL is std::allocator<T>::{,de}allocate. */ + +static inline bool +is_std_allocator_allocate (tree fndecl) +{ + tree name = DECL_NAME (fndecl); + if (name == NULL_TREE + || !(id_equal (name, "allocate") || id_equal (name, "deallocate"))) + return false; + + tree ctx = DECL_CONTEXT (fndecl); + if (ctx == NULL_TREE || !CLASS_TYPE_P (ctx) || !TYPE_MAIN_DECL (ctx)) + return false; + + tree decl = TYPE_MAIN_DECL (ctx); + name = DECL_NAME (decl); + if (name == NULL_TREE || !id_equal (name, "allocator")) + return false; + + return decl_in_std_namespace_p (decl); +} + /* Subroutine of cxx_eval_constant_expression. Evaluate the call expression tree T in the context of OLD_CALL expression evaluation. */ @@ -1716,7 +1738,12 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, lval, non_constant_p, overflow_p); if (!DECL_DECLARED_CONSTEXPR_P (fun)) { - if (cxx_replaceable_global_alloc_fn (fun)) + if (TREE_CODE (t) == CALL_EXPR + && cxx_replaceable_global_alloc_fn (fun) + && (CALL_FROM_NEW_OR_DELETE_P (t) + || (ctx->call + && ctx->call->fundef + && is_std_allocator_allocate (ctx->call->fundef->decl)))) { const int nargs = call_expr_nargs (t); tree arg0 = NULL_TREE; @@ -1774,7 +1801,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, } /* Allow placement new in std::construct_at, just return the second argument. */ - if (cxx_placement_new_fn (fun) + if (TREE_CODE (t) == CALL_EXPR + && cxx_placement_new_fn (fun) && ctx->call && ctx->call->fundef && is_std_construct_at (ctx->call->fundef->decl)) @@ -6508,9 +6536,15 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, && !fndecl_built_in_p (fun) /* In C++2a, replaceable global allocation functions are constant expressions. */ - && !cxx_replaceable_global_alloc_fn (fun) + && (!cxx_replaceable_global_alloc_fn (fun) + || TREE_CODE (t) != CALL_EXPR + || (!CALL_FROM_NEW_OR_DELETE_P (t) + && (current_function_decl == NULL_TREE + || !is_std_allocator_allocate + (current_function_decl)))) /* Allow placement new in std::construct_at. */ && (!cxx_placement_new_fn (fun) + || TREE_CODE (t) != CALL_EXPR || current_function_decl == NULL_TREE || !is_std_construct_at (current_function_decl))) { |