From 86461cad6f7b751c19fb96fefc62d8e119c8a351 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 18 Mar 2016 16:16:05 -0400 Subject: [PATCH] re PR c++/70139 (-fno-elide-constructor makes static std::regex to throw) PR c++/70139 * constexpr.c (cxx_eval_call_expression): Fix trivial copy. From-SVN: r234345 --- gcc/cp/ChangeLog | 3 ++ gcc/cp/constexpr.c | 47 +++++++++++-------- .../g++.dg/cpp0x/constexpr-trivial1.C | 20 ++++++++ 3 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-trivial1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9e1dbbb29df..cd98a53b0ac 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2016-03-18 Jason Merrill + PR c++/70139 + * constexpr.c (cxx_eval_call_expression): Fix trivial copy. + PR c++/70147 * class.c (vptr_via_virtual_p): New. (most_primary_binfo): Factor out of build_rtti_vtbl_entries. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 5f97c9dad19..1f496b5f9bd 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1239,19 +1239,39 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, return t; } + constexpr_ctx new_ctx = *ctx; + if (DECL_CONSTRUCTOR_P (fun) && !ctx->object + && TREE_CODE (t) == AGGR_INIT_EXPR) + { + /* We want to have an initialization target for an AGGR_INIT_EXPR. + If we don't already have one in CTX, use the AGGR_INIT_EXPR_SLOT. */ + new_ctx.object = AGGR_INIT_EXPR_SLOT (t); + tree ctor = new_ctx.ctor = build_constructor (DECL_CONTEXT (fun), NULL); + CONSTRUCTOR_NO_IMPLICIT_ZERO (ctor) = true; + ctx->values->put (new_ctx.object, ctor); + ctx = &new_ctx; + } + /* Shortcut trivial constructor/op=. */ if (trivial_fn_p (fun)) { + tree init = NULL_TREE; if (call_expr_nargs (t) == 2) - { - tree arg = convert_from_reference (get_nth_callarg (t, 1)); - return cxx_eval_constant_expression (ctx, arg, - lval, non_constant_p, - overflow_p); - } + init = convert_from_reference (get_nth_callarg (t, 1)); else if (TREE_CODE (t) == AGGR_INIT_EXPR && AGGR_INIT_ZERO_FIRST (t)) - return build_zero_init (DECL_CONTEXT (fun), NULL_TREE, false); + init = build_zero_init (DECL_CONTEXT (fun), NULL_TREE, false); + if (init) + { + tree op = get_nth_callarg (t, 0); + if (is_dummy_object (op)) + op = ctx->object; + else + op = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (op)), op); + tree set = build2 (MODIFY_EXPR, TREE_TYPE (op), op, init); + return cxx_eval_constant_expression (ctx, set, lval, + non_constant_p, overflow_p); + } } /* We can't defer instantiating the function any longer. */ @@ -1287,19 +1307,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, } } - constexpr_ctx new_ctx = *ctx; - if (DECL_CONSTRUCTOR_P (fun) && !ctx->object - && TREE_CODE (t) == AGGR_INIT_EXPR) - { - /* We want to have an initialization target for an AGGR_INIT_EXPR. - If we don't already have one in CTX, use the AGGR_INIT_EXPR_SLOT. */ - new_ctx.object = AGGR_INIT_EXPR_SLOT (t); - tree ctor = new_ctx.ctor = build_constructor (DECL_CONTEXT (fun), NULL); - CONSTRUCTOR_NO_IMPLICIT_ZERO (ctor) = true; - ctx->values->put (new_ctx.object, ctor); - ctx = &new_ctx; - } - bool non_constant_args = false; cxx_bind_parameters_in_call (ctx, t, &new_call, non_constant_p, overflow_p, &non_constant_args); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial1.C new file mode 100644 index 00000000000..f4b74a7eec9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial1.C @@ -0,0 +1,20 @@ +// PR c++/70139 +// { dg-options "-fno-elide-constructors" } +// { dg-do compile { target c++11 } } + +template +struct A +{ + T a; + U b; + constexpr A () : a (), b () { } + constexpr A (const T &x, const U &y) : a (x), b (y) { } +}; +struct B +{ + constexpr B (const bool x) : c (x) {} + constexpr bool operator!= (const B x) const { return c != x.c; } + bool c; +}; +constexpr static A d[] = { { B (true), nullptr }, { B (false), nullptr } }; +static_assert (d[0].a != d[1].a, ""); -- 2.30.2