From patchwork Tue Feb 11 20:00:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 1236450 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-519366-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=GpZvN70s; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=LCP7HOJv; dkim-atps=neutral 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 48HDDK35C3z9sRY for ; Wed, 12 Feb 2020 07:01:03 +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:from :subject:to:message-id:date:mime-version:content-type; q=dns; s= default; b=ZJV9IdebCXAkRqFvK8DnOAooP3BRvi5BqUeQ732LUklwwr6XsdEcg etn9iWtZkellcVA0w6vTEYQ8zmv4UEEU95wP1nWeOEk/CcHK1kQSom9MUcoP1bmn Ox7UB3eFAEWE0UK+oMB+EiUnkxI1uzsCmpfaGQ7rioaGaTqliT6Hrk= 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:from :subject:to:message-id:date:mime-version:content-type; s= default; bh=otTrtM/WJLdFjki34p3VhtR/PcU=; b=GpZvN70sx2RnPhbTwX1f WaQPFsEEcUTmXHIAD8Miowzn+34riasSDu98FRzUxoaPZYvOvyWXT4tZq60aHSVH ficnoOokYadp1x5UIZJo7NZci8elJIx3FMZBQzvrEc+Uvh3HbFCbFYKEErmPqQ+b eO0dNvFv3i0MVmW5qUR6smE= Received: (qmail 43565 invoked by alias); 11 Feb 2020 20:00:54 -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 43427 invoked by uid 89); 11 Feb 2020 20:00:42 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-19.3 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=qualify, HX-Languages-Length:4533 X-HELO: mail-qk1-f172.google.com Received: from mail-qk1-f172.google.com (HELO mail-qk1-f172.google.com) (209.85.222.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 11 Feb 2020 20:00:21 +0000 Received: by mail-qk1-f172.google.com with SMTP id v2so6497565qkj.2 for ; Tue, 11 Feb 2020 12:00:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:subject:to:message-id:date:user-agent:mime-version :content-language; bh=ZDaie/BpzYTvaP/tVV+Ovsd2TXP3mOgr+4JOAT8jYDA=; b=LCP7HOJvQLos5m88adFu3VU3tscGaMI+dBJbBLpCOx/TjUzYtbcwmPVH4cAduUCNga E8xmUwXse9dGmK1NdcLKVJ1xVO+QHgEnVDbQIUNdvNwK0GkqczwCRrSXNmBDlFrNqT1u Jc+6LfRUhOH8cq0LBT2lTWOPLVj4NeOYs9IJsimiNiiYwJkB85WG9QgLvM1QyTpy8fNl EPQpNFLKZn8Sps6lSD+c8MTBriIdv5WEMeVZIIGREdqQHbFjo/TrjLaKtp4++HMVWQtd IXRbYEsrLybD4q86kG0s7/p4z2ZH9WZ8Y1ZTa3/hR6tK6AcrWleNxdiMB8XRt52hKMal Wrcw== Received: from [192.168.0.41] (174-16-112-158.hlrn.qwest.net. [174.16.112.158]) by smtp.gmail.com with ESMTPSA id k7sm2745794qtd.79.2020.02.11.12.00.06 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 11 Feb 2020 12:00:06 -0800 (PST) From: Martin Sebor Subject: [PATCH] avoid user-constructible types in reshape_init_array (PR 90938) To: gcc-patches , Jason Merrill Message-ID: Date: Tue, 11 Feb 2020 13:00:05 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 X-IsSubscribed: yes r270155, committed in GCC 9, introduced a transformation that strips redundant trailing zero initializers from array initializer lists in order to support string literals as template arguments. The transformation neglected to consider the case of array elements of trivial class types with user-defined conversion ctors and either defaulted or deleted default ctors. (It didn't occur to me that those qualify as trivial types despite the user-defined ctors.) As a result, some valid initialization expressions are rejected when the explicit zero-initializers are dropped in favor of the (deleted) default ctor, and others are eliminated in favor of the defaulted ctor instead of invoking a user-defined conversion ctor, leading to wrong code. The attached patch fixes that but avoiding this transformation for such types. Tested on x86_64-linux. I'd like to commit the patch to both trunk and to GCC 9 (with testsuite adjustments if necessary). Martin PR c++/90938 - Initializing array with {1} works but not {0} gcc/cp/ChangeLog: PR c++/90938 * decl.c (reshape_init_array_1): Avoid types with non-trivial user-defined ctors. gcc/testsuite/ChangeLog: PR c++/90938 * g++.dg/init/array55.C: New test. * g++.dg/init/array56.C: New test. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 31a556a0a1f..60731cb3f9d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6051,11 +6051,14 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, break; } - if (sized_array_p && trivial_type_p (elt_type)) + if (sized_array_p + && trivial_type_p (elt_type) + && !TYPE_NEEDS_CONSTRUCTING (elt_type)) { /* Strip trailing zero-initializers from an array of a trivial - type of known size. They are redundant and get in the way - of telling them apart from those with implicit zero value. */ + type with no user-defined ctor of known size. They are + redundant and get in the way of telling them apart from those + with implicit zero value. */ unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (new_init); if (last_nonzero > nelts) nelts = 0; diff --git a/gcc/testsuite/g++.dg/init/array55.C b/gcc/testsuite/g++.dg/init/array55.C new file mode 100644 index 00000000000..00a4cf6c616 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array55.C @@ -0,0 +1,12 @@ +/* PR c++/90938 - Initializing array with {1} works, but not {0} + { dg-do compile { target c++11 } } */ + +struct X +{ + X () = delete; + X (int) { } +}; + +X x0[1] { 1 }; +X x1[1] { 0 }; +X x2[1] { }; // { dg-error "use of deleted function" } diff --git a/gcc/testsuite/g++.dg/init/array56.C b/gcc/testsuite/g++.dg/init/array56.C new file mode 100644 index 00000000000..63e16663ec1 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array56.C @@ -0,0 +1,107 @@ +/* PR c++/90938 - Initializing array with {1} works, but not {0} + { dg-do compile { target c++11 } } + { dg-options "-O -Wall -fdump-tree-optimized" } */ + +#define assert(e) \ + ((e) ? (void)0 \ + : (__builtin_printf ("assertion failed on line %i: %s\n", \ + __LINE__, #e), \ + __builtin_abort ())) + +namespace A { + +struct X +{ + X () = default; + X (int n) : n (n + 1) { } + int n; +}; + +static_assert (__is_trivial (X), "X is trivial"); + +static void test () +{ + { + X x[] { 0 }; + assert (1 == x->n); + } + + { + X x[1] { 0 }; + assert (1 == x->n); // fails + } + + { + X x[2] { 0 }; + assert (1 == x[0].n && 0 == x[1].n); // fails + } + + { + X x[] { 1, 0 }; + assert (2 == x[0].n && 1 == x[1].n); // passes + } + + { + X x[2] { 1, 0 }; + assert (2 == x[0].n && 1 == x[1].n); // fails + } +} + +} + +namespace B { + +struct X +{ + X () = default; + X (int *p) : p (p ? p : new int (1)) { } + int *p; +}; + +static_assert (__is_trivial (X), "X is trivial"); + +static void test () +{ + X x[1] { nullptr }; + assert (*x->p == 1); // fails + + X y[1] { 0 }; + assert (*y->p == 1); // fails +} + +} + +namespace C { + +static const char *vector_swizzle (int vecsize, int index) +{ + static const char *swizzle[4][4] = + { + { ".x", ".y", ".z", ".w" }, + { ".xy", ".yz", ".zw", nullptr }, + { ".xyz", ".yzw", nullptr, nullptr }, + { "", nullptr, nullptr, nullptr }, + }; + + assert (vecsize >= 1 && vecsize <= 4); + assert (index >= 0 && index < 4); + assert (swizzle[vecsize - 1][index]); + + return swizzle[vecsize - 1][index]; +} + +static void test () +{ + assert (!*vector_swizzle(4, 0)); +} + +} + +int main () +{ + A::test (); + B::test (); + C::test (); +} + +// { dg-final { scan-tree-dump-not "abort" "optimized" } }