From patchwork Fri Mar 18 20:15:23 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 599664 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3qRc0q01YPz9s4x for ; Sat, 19 Mar 2016 07:15:38 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=Bs/+NPf8; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=JFg1R176UD5ln4j1WtcU/S10wID04CywzTpaOGv3FJlipROb74 qcrZ5bKNmvVCtDdvTXnPA8nA0XvJLLVKouW4ktkbT8OMxO0uMvp8/cz5wh7PML4L bCgURoFkeEr6YfrHf8M5zyUewMd9+5Ubmek1Vi3WK4FzGzk95rx5JMwVo= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=I9RfHVhMw3jC+CPKO0dDizfl7Yg=; b=Bs/+NPf83U1w0ZflSyQO dsW4JFRHCYEGcnKidl+s36f2Zw1CAHcgxC5t47Kgafp9LsYIRK1G3zzZIUNmCJJE NzCgn55chjtGqbYy4i1dsNU2k+COBgCumX851auo/7UBAGcDNuo4Du4Lmg8xnyp/ x2tm4MUqtHUgTY4qaktqdOo= Received: (qmail 7198 invoked by alias); 18 Mar 2016 20:15:28 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 7188 invoked by uid 89); 18 Mar 2016 20:15:27 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=UD:object, !ctx, sk:CONSTRU, CTX X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 18 Mar 2016 20:15:25 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (Postfix) with ESMTPS id 7AE71461D2 for ; Fri, 18 Mar 2016 20:15:24 +0000 (UTC) Received: from [10.3.113.58] (ovpn-113-58.phx2.redhat.com [10.3.113.58]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u2IKFNE0012314 for ; Fri, 18 Mar 2016 16:15:24 -0400 To: gcc-patches List From: Jason Merrill Subject: C++ PATCH for c++/70139 (-fno-elide-constructors breaks regex) Message-ID: <56EC61DB.3010006@redhat.com> Date: Fri, 18 Mar 2016 16:15:23 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 The constexpr code for shortcutting trivial copy ctor/op= didn't get updated for the C++14 constexpr implementation, where we need to consider side effects. For GCC 5.4 I'm just going to disable the shortcut. Tested x86_64-pc-linux-gnu, applying to trunk. commit a805189949e8ed36713d5eb78c283a5000566bf0 Author: Jason Merrill Date: Fri Mar 18 14:57:58 2016 -0400 PR c++/70139 * constexpr.c (cxx_eval_call_expression): Fix trivial copy. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 5f97c9d..1f496b5 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 0000000..f4b74a7 --- /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, "");