From patchwork Wed Dec 7 20:31:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 87170 Delivered-To: patch@linaro.org Received: by 10.140.20.101 with SMTP id 92csp510697qgi; Wed, 7 Dec 2016 12:32:09 -0800 (PST) X-Received: by 10.84.208.102 with SMTP id f35mr149775761plh.137.1481142729329; Wed, 07 Dec 2016 12:32:09 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id 90si25387736pla.214.2016.12.07.12.32.09 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Dec 2016 12:32:09 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-443731-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-443731-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-443731-patch=linaro.org@gcc.gnu.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=Qlee97qXNTgPw/2Y6fb9xn48mZPPX8+I3in836z62fpj0XkWDI E0mAdpEdkPAM/rcLkQHv808KPUGnhNr8Z0NOYai1Xxm57DQWY0D+TyiSlIda4mC+ QuEfZQa5A3v8R4IYAzvP4jXaEe9ejR0ojbONibGdH3cLpoDzywXp0tzIE= 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:cc :from:subject:message-id:date:mime-version:content-type; s= default; bh=5VsaHVp2P4h2wcLR77Oi6wSykGk=; b=v2jaXYQ5NS3txiShRLfE ycHs8rhLqg/aowbHVgJQh7u9Z31fBxxqiO4uKdG8He8vaiNBvrogqzczeaVHM41r hcT3GxL5ELKRlLxeoACmfCRcn9xDcYW8JbtwaYHg8lUtlYNTChCwgFS5QcmDp4OJ 4rZfxPonEIEPhz9mvCT8vDo= Received: (qmail 22053 invoked by alias); 7 Dec 2016 20:31:52 -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 22043 invoked by uid 89); 7 Dec 2016 20:31:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.3 required=5.0 tests=BAYES_00, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=herring, cd, Subroutine, c.d X-HELO: mail-qt0-f195.google.com Received: from mail-qt0-f195.google.com (HELO mail-qt0-f195.google.com) (209.85.216.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 07 Dec 2016 20:31:42 +0000 Received: by mail-qt0-f195.google.com with SMTP id n34so46286874qtb.3 for ; Wed, 07 Dec 2016 12:31:41 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:to:cc:from:subject:message-id:date :user-agent:mime-version; bh=AKJQOkQA/P3WNRilsI5ryz3sA6raHcCbo1MPQh+/cMI=; b=ZM0kl5OmQUOmVSH+yVwoia3iIifeC4tCJNV4EZwf/d1LiwmoNWC9Ho/43i6uwVozs3 g2v461+dweteitFSOK7806PiGd41ptte2cYndUUiUhW4W3q5BpTvm0h6vA/T14q4oaxs /YPILTiF+tfj4pcyjScINZLw7aBGEPcopiZXHR7rvO8thQg64ufLSLPgSRynT9NRu+eh 019ptty2l0wUgXv0lQfstGYUALNXLua6O4+7ivgoHeeuB8KZA9XjWzklRU/j2PppgG/F qY+99gaaGiP9Sc96md3p2sPxAx6lbWut4zweqVGjkCRTEO0g/B9BL+/XCf91h7V90NDI 6W7Q== X-Gm-Message-State: AKaTC00XWcU5RQkj0lxBn6tqGqhWXdVDLpAtFBVpzclTwzPZgrmzs7zKNhLHAk3Dkzk/dQ== X-Received: by 10.37.163.33 with SMTP id d30mr35391444ybi.54.1481142699122; Wed, 07 Dec 2016 12:31:39 -0800 (PST) Received: from ?IPv6:2620:10d:c0a3:20fb:f6d0:5ac5:64cd:f102? ([2620:10d:c091:200::a:6eb0]) by smtp.googlemail.com with ESMTPSA id m136sm10625899ywd.19.2016.12.07.12.31.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Dec 2016 12:31:38 -0800 (PST) To: Jason Merrill Cc: GCC Patches From: Nathan Sidwell Subject: [PATCH] fix c++/78551 ICE in constexpr Message-ID: <4dc1a06a-35d5-0f01-5880-ecfb7a587d30@acm.org> Date: Wed, 7 Dec 2016 15:31:37 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 This patch fixes 78551. The union was a red herring. The underlying problem is that we first initialize a char array with a string constant, and then zap a random element of that array. That zapping expects to see a CONSTRUCTOR, not a STRING_CST. Fixed by expanding the STRING_CST into a CONSTRUCTOR for each element, when we encounter this situation. Patch tested on HEAD and gcc-6 branch. Is gcc-5 still live (testcase is marked as a 5/6/7 regression)? nathan -- Nathan Sidwell 2016-12-07 Nathan Sidwell PR c++/78551 * constexpr.c (extract_string_elt): New. Broken out of ... (cxx_eval_array_reference): ... here. Call it. (cxx_eval_store_expression): Convert init by STRING_CST into CONSTRUCTOR, if needed. PR c++/78551 * g++.dg/cpp1y/pr78551.C: New. Index: cp/constexpr.c =================================================================== --- cp/constexpr.c (revision 243344) +++ cp/constexpr.c (working copy) @@ -2149,6 +2149,27 @@ diag_array_subscript (const constexpr_ct } } +/* Extract element INDEX consisting of CHARS_PER_ELT chars from + STRING_CST STRING. */ + +static tree +extract_string_elt (tree string, unsigned chars_per_elt, unsigned index) +{ + tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (string))); + tree r; + + if (chars_per_elt == 1) + r = build_int_cst (type, TREE_STRING_POINTER (string)[index]); + else + { + const unsigned char *ptr + = ((const unsigned char *)TREE_STRING_POINTER (string) + + index * chars_per_elt); + r = native_interpret_expr (type, ptr, chars_per_elt); + } + return r; +} + /* Subroutine of cxx_eval_constant_expression. Attempt to reduce a reference to an array slot. */ @@ -2244,16 +2265,9 @@ cxx_eval_array_reference (const constexp r = (*CONSTRUCTOR_ELTS (ary))[i].value; else if (TREE_CODE (ary) == VECTOR_CST) r = VECTOR_CST_ELT (ary, i); - else if (elem_nchars == 1) - r = build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))), - TREE_STRING_POINTER (ary)[i]); else - { - tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (ary))); - r = native_interpret_expr (type, (const unsigned char *) - TREE_STRING_POINTER (ary) - + i * elem_nchars, elem_nchars); - } + r = extract_string_elt (ary, elem_nchars, i); + if (r) /* Don't VERIFY_CONSTANT here. */ return r; @@ -3326,6 +3340,35 @@ cxx_eval_store_expression (const constex *valp = build_constructor (type, NULL); CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp) = no_zero_init; } + else if (TREE_CODE (*valp) == STRING_CST) + { + /* An array was initialized with a string constant, and now + we're writing into one of its elements. Explode the + single initialization into a set of element + initializations. */ + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); + + tree string = *valp; + tree elt_type = TREE_TYPE (type); + unsigned chars_per_elt = (TYPE_PRECISION (elt_type) + / TYPE_PRECISION (char_type_node)); + unsigned num_elts = TREE_STRING_LENGTH (string) / chars_per_elt; + tree ary_ctor = build_constructor (type, NULL); + + vec_safe_reserve (CONSTRUCTOR_ELTS (ary_ctor), num_elts); + for (unsigned ix = 0; ix != num_elts; ix++) + { + constructor_elt elt = + { + build_int_cst (size_type_node, ix), + extract_string_elt (string, chars_per_elt, ix) + }; + CONSTRUCTOR_ELTS (ary_ctor)->quick_push (elt); + } + + *valp = ary_ctor; + } + /* If the value of object is already zero-initialized, any new ctors for subobjects will also be zero-initialized. */ no_zero_init = CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp); Index: testsuite/g++.dg/cpp1y/pr78551.C =================================================================== --- testsuite/g++.dg/cpp1y/pr78551.C (nonexistent) +++ testsuite/g++.dg/cpp1y/pr78551.C (working copy) @@ -0,0 +1,32 @@ +// { dg-do compile { target c++14 } } + +// PR c++/78551 ICE in constexpr evaluation overwriting array +// intialized by string constant. + +constexpr char Foo (char x, int ix) +{ + char d[4] = "012"; + d[0] = x; + return d[ix]; +} + +static const char a = Foo ('a', 1); +static const char b = Foo ('a', 0); + +static_assert (a == '1', ""); +static_assert (b == 'a', ""); + +struct A { + union { + long s; + char d[4]; + }; + constexpr A (char x) + : d("012") + { d[0] = x; } +}; + +static constexpr A c{'a'}; + +static_assert (c.d[0] == 'a', ""); +static_assert (c.d[1] == '1', "");