From patchwork Thu Jul 30 21:46:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1339134 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=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=Clx5K0nw; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BHkWC2nXJz9sT6 for ; Fri, 31 Jul 2020 07:46:15 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A8B993857C5D; Thu, 30 Jul 2020 21:46:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A8B993857C5D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1596145572; bh=cgqsaOflV+qUGRgy8tckKTX4Tzkf9WLpZpS6C7CMYUI=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=Clx5K0nwztDm+S40j2ud4uk/2zdOZ1bRWbiRsVwB5JEud27J1QSGdw4fPpFtJalpU PmJWocWxGLFyxYhi+jHMxgGpftAXmig9oUcBMEnaKnCHeAkxgP1r0J3pW4M8KN/y6M 3hLw3dJLzft19MRgAU+z43pMzy1/QSGNq8cApxC4= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [80.241.56.151]) by sourceware.org (Postfix) with ESMTPS id AD3293858D35 for ; Thu, 30 Jul 2020 21:46:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org AD3293858D35 Received: from smtp2.mailbox.org (smtp2.mailbox.org [80.241.60.241]) (using TLSv1.2 with cipher ECDHE-RSA-CHACHA20-POLY1305 (256/256 bits)) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4BHkW4257xzKmbx; Thu, 30 Jul 2020 23:46:08 +0200 (CEST) X-Virus-Scanned: amavisd-new at heinlein-support.de Received: from smtp2.mailbox.org ([80.241.60.241]) by spamfilter02.heinlein-hosting.de (spamfilter02.heinlein-hosting.de [80.241.56.116]) (amavisd-new, port 10030) with ESMTP id ayWa2NwdqA0c; Thu, 30 Jul 2020 23:46:03 +0200 (CEST) To: gcc-patches@gcc.gnu.org Subject: [committed] d: Fix associative array literals that don't have alignment holes filled (PR96152) Date: Thu, 30 Jul 2020 23:46:01 +0200 Message-Id: <20200730214601.789943-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-MBO-SPAM-Probability: 34 X-Rspamd-Score: 5.11 / 15.00 / 15.00 X-Rspamd-Queue-Id: D5BE11790 X-Rspamd-UID: 0ef4ef X-Spam-Status: No, score=-16.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_ABUSE_SURBL, URIBL_RED autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch fixes an assert that is triggered at run-time due to the hash of an associative array literal not matching a non-literal with the same contents. Associative array literals are now filled using memset() prior to usage, with LTR evalution of side-effects enforced. Bootstrapped and regression tested on x86_64-linux-gnu, committed to mainline. Regards Iain. --- gcc/d/ChangeLog: PR d/96152 * d-codegen.cc (build_array_from_exprs): New function. * d-tree.h (build_array_from_exprs): Declare. * expr.cc (ExprVisitor::visit (AssocArrayLiteralExp *)): Use build_array_from_exprs to generate key and value arrays. gcc/testsuite/ChangeLog: PR d/96152 * gdc.dg/pr96152.d: New test. --- gcc/d/d-codegen.cc | 36 ++++++++++++++++++++++++++++++++++ gcc/d/d-tree.h | 1 + gcc/d/expr.cc | 33 +++++++++---------------------- gcc/testsuite/gdc.dg/pr96152.d | 32 ++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/gdc.dg/pr96152.d diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index a38aa6c55e0..2dce09d7187 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -1722,6 +1722,42 @@ build_array_from_val (Type *type, tree val) return build_constructor (build_ctype (type), elms); } +/* Build a static array of type TYPE from an array of EXPS. + If CONST_P is true, then all elements in EXPS are constants. */ + +tree +build_array_from_exprs (Type *type, Expressions *exps, bool const_p) +{ + /* Build a CONSTRUCTOR from all expressions. */ + vec *elms = NULL; + vec_safe_reserve (elms, exps->length); + + Type *etype = type->nextOf (); + tree satype = make_array_type (etype, exps->length); + + for (size_t i = 0; i < exps->length; i++) + { + Expression *expr = (*exps)[i]; + tree t = build_expr (expr, const_p); + CONSTRUCTOR_APPEND_ELT (elms, size_int (i), + convert_expr (t, expr->type, etype)); + } + + /* Create a new temporary to store the array. */ + tree var = build_local_temp (satype); + + /* Fill any alignment holes with zeroes. */ + TypeStruct *ts = etype->baseElemOf ()->isTypeStruct (); + tree init = NULL; + if (ts && (!identity_compare_p (ts->sym) || ts->sym->isUnionDeclaration ())) + init = build_memset_call (var); + + /* Initialize the temporary. */ + tree assign = modify_expr (var, build_constructor (satype, elms)); + return compound_expr (compound_expr (init, assign), var); +} + + /* Implicitly converts void* T to byte* as D allows { void[] a; &a[3]; } */ tree diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 48c8ef09dd1..df317d557eb 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -562,6 +562,7 @@ extern tree build_offset (tree, tree); extern tree build_memref (tree, tree, tree); extern tree build_array_set (tree, tree, tree); extern tree build_array_from_val (Type *, tree); +extern tree build_array_from_exprs (Type *, Expressions *, bool); extern tree void_okay_p (tree); extern tree build_array_bounds_call (const Loc &); extern tree build_bounds_condition (const Loc &, tree, tree, bool); diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 355561a481e..20ab49d7b8c 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -2799,30 +2799,14 @@ public: /* Build an expression that assigns all expressions in KEYS to a constructor. */ - vec *kelts = NULL; - vec_safe_reserve (kelts, e->keys->length); - for (size_t i = 0; i < e->keys->length; i++) - { - Expression *key = (*e->keys)[i]; - tree t = build_expr (key); - CONSTRUCTOR_APPEND_ELT (kelts, size_int (i), - convert_expr (t, key->type, ta->index)); - } - tree tkeys = make_array_type (ta->index, e->keys->length); - tree akeys = build_constructor (tkeys, kelts); + tree akeys = build_array_from_exprs (ta->index->sarrayOf (e->keys->length), + e->keys, this->constp_); + tree init = stabilize_expr (&akeys); /* Do the same with all expressions in VALUES. */ - vec *velts = NULL; - vec_safe_reserve (velts, e->values->length); - for (size_t i = 0; i < e->values->length; i++) - { - Expression *value = (*e->values)[i]; - tree t = build_expr (value); - CONSTRUCTOR_APPEND_ELT (velts, size_int (i), - convert_expr (t, value->type, ta->next)); - } - tree tvals = make_array_type (ta->next, e->values->length); - tree avals = build_constructor (tvals, velts); + tree avals = build_array_from_exprs (ta->next->sarrayOf (e->values->length), + e->values, this->constp_); + init = compound_expr (init, stabilize_expr (&avals)); /* Generate: _d_assocarrayliteralTX (ti, keys, vals); */ tree keys = d_array_value (build_ctype (ta->index->arrayOf ()), @@ -2840,8 +2824,9 @@ public: vec *ce = NULL; CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (aatype), mem); - this->result_ = build_nop (build_ctype (e->type), - build_constructor (aatype, ce)); + tree result = build_nop (build_ctype (e->type), + build_constructor (aatype, ce)); + this->result_ = compound_expr (init, result); } /* Build a struct literal. */ diff --git a/gcc/testsuite/gdc.dg/pr96152.d b/gcc/testsuite/gdc.dg/pr96152.d new file mode 100644 index 00000000000..3551614654b --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr96152.d @@ -0,0 +1,32 @@ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96152 +// { dg-additional-options "-fmain -funittest" } +// { dg-do run { target hw } } +// { dg-skip-if "needs gcc/config.d" { ! d_runtime } } +auto assocArray(Keys, Values)(Keys keys, Values values) +{ + void* aa; + { + if (values.length > keys.length) + values = values[0 .. keys.length]; + else if (keys.length > values.length) + keys = keys[0 .. values.length]; + aa = aaLiteral(keys, values); + } + alias Key = typeof(keys[0]); + alias Value = typeof(values[0]); + return (() @trusted => cast(Value[Key]) aa)(); +} + +@safe unittest +{ + struct ThrowingElement + { + int i; + static bool b; + ~this(){ + if (b) + throw new Exception(""); + } + } + assert(assocArray([ThrowingElement()], [0]) == [ThrowingElement(): 0]); +}