From patchwork Tue Dec 20 16:25:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 707498 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 3tjjpX0Gp3z9t5m for ; Wed, 21 Dec 2016 03:26:26 +1100 (AEDT) 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=PJl/eNukdhwo5I40CJHXl1ZozXmfkxlpCs9UwrJ+qEA5GKQaOg giHgzj+NqRMqv79rmew5PewYkI0gi/XPHK2EyVqM5aJSwWxsNKx4fp9YHf5lgguG f0OwJv3DNG1A5Eycy5vCiGUYsBkiaIGcesMk3CCaNtHtbNcmtwdckQUHM= 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=lcR1CEzFP5PR/x/zIJpz0RyLTu8=; b=o/J5vr/bS7yBZRY4La+l oFCN0DmJcwk6gN0nFMkq/gUOFbx0/2dg31xyt8DfPzbgvcEX75x5VlN57rdYoGdy gNR3Ab4fov4eusNuO/BhT3gePhtvkdC5TS5x+AB8rvJwmlkp7vNLuhjtNvn2bQ8B YsVCMoDn2b9xlXHa+YTxV1c= Received: (qmail 106385 invoked by alias); 20 Dec 2016 16:25:41 -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 106324 invoked by uid 89); 20 Dec 2016 16:25:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-5.0 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=varasm, our 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 ESMTP; Tue, 20 Dec 2016 16:25:38 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9B0AEA1F72 for ; Tue, 20 Dec 2016 16:25:37 +0000 (UTC) Received: from abulafia.quesejoda.com (ovpn-117-2.ams2.redhat.com [10.36.117.2]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id uBKGPZbc031268; Tue, 20 Dec 2016 11:25:36 -0500 To: jason merrill , gcc-patches From: Aldy Hernandez Subject: [PR c++/78572] handle array self references in intializers Message-ID: Date: Tue, 20 Dec 2016 11:25:34 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 The problem in this PR is that we're trying to initialize an array with members of itself: int array[10] = { array[3]=5, array[7]=3 }; The C++ front-end, in store_init_value() via cxx_constant_value() and friends will transform: {array[3] = 5, array[7] = 3} into: {[3]=5, [0]=5, [7]=3, [1]=3} which looks invalid to output_constructor*(), presumably because it isn't sorted by increasing index. Jakub has even gone further to show that for the following: ... = { array[3]=5, array[7]=3, array[7]=8, array[7] = 9 }; things get even worse, because we generate code to write twice into [3]: {[3]=5, [0]=5, [7]=9, [1]=3, [2]=8, [3]=9} I took the easy way in cxx_eval_store_expression() and marked the expression as non_constant_p if we're trying to set an array from members of itself. This causes us to to generate the initialization of the self-referencing array[sub] elements as a CLEANUP_POINT_EXPR: <>>>>; <>>>>; Ultimately this yields correct code: array: .zero 40 ... ... _GLOBAL__sub_I_array: .LFB1: .cfi_startproc movl $5, array+12(%rip) movl $5, array(%rip) movl $3, array+28(%rip) movl $3, array+4(%rip) ret Is this approach acceptable, or should we be marking this as non-constant somewhere else in the chain? Or perhaps another approach would be to handle such constructor holes in the in the varasm code? Aldy commit 295d93f60bcbec5b9959a7b3656f10aa0df71c9f Author: Aldy Hernandez Date: Tue Dec 20 06:13:26 2016 -0500 PR c++/78572 * constexpr.c (cxx_eval_store_expression): Avoid array self references in initialization. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index aedd004..ac279ad 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3313,6 +3313,15 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, } } + /* Initializing an array from a variant of itself is a non-constant. + This avoids attemps at generating incorrect self references in + something like: int foo[10] = { stuff[3]=8 }. */ + if (TREE_CODE (target) == ARRAY_REF && object == ctx->object) + { + *non_constant_p = true; + return t; + } + /* And then find/build up our initializer for the path to the subobject we're initializing. */ tree *valp; diff --git a/gcc/testsuite/g++.dg/pr78572.C b/gcc/testsuite/g++.dg/pr78572.C new file mode 100644 index 0000000..82ab4e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr78572.C @@ -0,0 +1,9 @@ +// { dg-do compile } */ + +static int array[10] = { array[3]=5, array[7]=3 }; + +int +main () +{ + return 0; +}