From patchwork Sun Oct 29 19:25:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 159404 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:d641:0:b0:403:3b70:6f57 with SMTP id cy1csp1825424vqb; Sun, 29 Oct 2023 12:25:54 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHF4/i1LA04JgmaVf23QFqkhxzsUB6WJW01MVBcynPVAF8X9ktgHCubbOhTDBP1X4jiIrnr X-Received: by 2002:a05:6214:2427:b0:66d:4766:5a83 with SMTP id gy7-20020a056214242700b0066d47665a83mr9837001qvb.16.1698607554688; Sun, 29 Oct 2023 12:25:54 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1698607554; cv=pass; d=google.com; s=arc-20160816; b=rH7iP5zPYsHjXYM/2s3ZCV+/WG65HZxZxomzCpJYNdpmctKO13yGKCzDJcRnU03Uvj RPML1X0QEff8gasQOkgYi+uVVlR602jXyLxl7k09ko9uuZ1NG5ZzYtgKYtk6pWSWfyNt VhBg7qNzSGASvGu+L1aEQlJ7DtRp4Zhk/IAVrIXuIdU2hIMBmjgz6ISwVopgzHRv78Ee Qe2Ts3c5WKW+WtoSCpwE7HDH0YL6+RgQeVWaZSatZtaXM16HrHNlHO3mKkvk6Cw6u9t9 PS1LPDB4QrN5ErRKspvfoJCwcf9LPGGi+B+6kzVzbIA7RKpf39CzIVx/qvdoAjVg/J3t CbaA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=kOLzD3Yr7eFMhT4noC30POySYhcC4hlqelWsIh3+PgU=; fh=D2tRalIjW6KCgVuqwFHStdMb9uqe8HSQc2WEvRJ6uLE=; b=wkPPausQfIYfsaFrC8bOqbkazPK2A4Vqa/TOSK2YYJBHYamJ/d9seUpGnwSjIZrvjI G/DeGgut6ZP/67iyhvQ86JUHlQM1L8oXGzRba+EMfzcbc5NfFNcqfxUT8buMgwqbJNs0 u0GPIN7MMa6BkwIV4cjflwVh/4+utXG+PFpg0EmdYeJQzU1DXxxabN1ruNkTY9S208L8 fBVk1lPnAQT565UHIDfDJL/H65gMfm3ZtFyIoHZ9ecll5Xy0MNk43tZ5Z82ptP+6cwZZ jVDXKs+I3YU+OVMunnuIXeZ5iLf3N+lnViTKYhZPyokfBbCZbTJPnY3bSvUks6LNQiph ft6g== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@gdcproject.org header.s=MBO0001 header.b=r9GJ4+bc; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=gdcproject.org Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id f4-20020a0ccc84000000b0065aea855463si4379664qvl.81.2023.10.29.12.25.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 29 Oct 2023 12:25:54 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gdcproject.org header.s=MBO0001 header.b=r9GJ4+bc; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=gdcproject.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7126A3864C64 for ; Sun, 29 Oct 2023 19:25:54 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-201.mailbox.org (mout-p-201.mailbox.org [80.241.56.171]) by sourceware.org (Postfix) with ESMTPS id F30CE385DC19 for ; Sun, 29 Oct 2023 19:25:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F30CE385DC19 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=gdcproject.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gdcproject.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org F30CE385DC19 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=80.241.56.171 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698607532; cv=none; b=t1JnrorhxxlIzr4NuFlKyM3P6mZeQhN2wMG34+E/IHUiBQQWaYgZCCRF+HIrAsOeb+/ZvFVWszpF+vf4EamAVurw5IVDLqpJ+D82hmnq/rTnAqUrMelwUproq3mRsibJrts54yHPslkPSHsAQFH2PwmIJzY5+M7yKvYtqscEsNE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698607532; c=relaxed/simple; bh=q4xvdZy1xhb20i3EOALnHfi1QeerdxLjb2b2Vef1Zaw=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=kJhWvQZpXzTkAFLAKeULpE9U8NAgZfxSgOMUGsEpzNQoAsXc3xMqF9NPtPN5eltYpdTq5X9akUWmQo/bja8XYAjN5Y1F3JaU1NRb5FahfHV4HWMGsl67S/WUl4GJ0xD9aYAes0VEV0jMMa3gtee/YtqjkC7SCPvy8AvV/gwSJqk= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smtp202.mailbox.org (smtp202.mailbox.org [IPv6:2001:67c:2050:b231:465::202]) (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 mout-p-201.mailbox.org (Postfix) with ESMTPS id 4SJRFM0RhKz9sW3; Sun, 29 Oct 2023 20:25:27 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gdcproject.org; s=MBO0001; t=1698607527; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=kOLzD3Yr7eFMhT4noC30POySYhcC4hlqelWsIh3+PgU=; b=r9GJ4+bclLEr3KCTpu9CbTo2IHKNKfvVInkcMXUEIwc55E6FwPJYG9f/9cVbphHwZgnR2d Y63ilrS1FBtQZV5NFMbsWWDF+bq7vJdaZrbG2sAyuYYuwj3mg0E2+JBn3UTwRLbsL9S1wQ nrssmH0oftol54AP+VzfCNEuO6yFj9+YVQAfyoGt7tKuCWHe9cVT3e+cm+Qaouh/yy90Qo JmqX7oP+6kotIgIPMWrik4tpZYrmAXm6MOfSQTqo7WbeT7zehDQqj9altTbZRvfHtUqGl5 9n6XoOmwDbNtSAD0yuLqStXVWx7YnFvQKFukYBLnzfLpKWQU1lnBi8useKVdOg== From: Iain Buclaw To: gcc-patches@gcc.gnu.org Cc: Iain Buclaw Subject: [committed] d: Fix ICE: verify_gimple_failed (conversion of register to a different size in 'view_convert_expr') [PR110712] Date: Sun, 29 Oct 2023 20:25:24 +0100 Message-Id: <20231029192524.202262-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4SJRFM0RhKz9sW3 X-Spam-Status: No, score=-13.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1781119115142946976 X-GMAIL-MSGID: 1781119115142946976 Hi, This patch fixes an ICE cause by the way the D front-end generates its codegen around va_list types. Static arrays in D are passed around by value, rather than decaying to a pointer. On x86_64 __builtin_va_list is an exception to this rule, but semantically it's still treated as a static array. This makes certain assignment operations fail due a mismatch in types. As all examples in the test program are rejected by C/C++ front-ends, these are now errors in D too to be consistent. Bootstrapped and regression tested on x86-64-linux-gnu/-m32, committed to mainline and backported to releases/gcc-12 and releases/gcc-13. Regards, Iain. --- PR d/110712 gcc/d/ChangeLog: * d-codegen.cc (d_build_call): Update call to convert_for_argument. * d-convert.cc (is_valist_parameter_type): New function. (check_valist_conversion): New function. (convert_for_assignment): Update signature. Add check whether assigning va_list is permissible. (convert_for_argument): Likewise. * d-tree.h (convert_for_assignment): Update signature. (convert_for_argument): Likewise. * expr.cc (ExprVisitor::visit (AssignExp *)): Update call to convert_for_assignment. gcc/testsuite/ChangeLog: * gdc.dg/pr110712.d: New test. --- gcc/d/d-codegen.cc | 6 +- gcc/d/d-convert.cc | 127 ++++++++++++++++++++++++++------ gcc/d/d-tree.h | 4 +- gcc/d/expr.cc | 12 +-- gcc/testsuite/gdc.dg/pr110712.d | 23 ++++++ 5 files changed, 139 insertions(+), 33 deletions(-) create mode 100644 gcc/testsuite/gdc.dg/pr110712.d diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index 270cb5e2be6..5c53cf78577 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -2245,14 +2245,16 @@ d_build_call (TypeFunction *tf, tree callable, tree object, for (size_t i = 0; i < arguments->length; ++i) { Expression *arg = (*arguments)[i]; - tree targ = build_expr (arg); + tree targ; if (i - varargs < nparams && i >= varargs) { /* Actual arguments for declared formal arguments. */ Parameter *parg = tf->parameterList[i - varargs]; - targ = convert_for_argument (targ, parg); + targ = convert_for_argument (arg, parg); } + else + targ = build_expr (arg); /* Don't pass empty aggregates by value. */ if (empty_aggregate_p (TREE_TYPE (targ)) && !TREE_ADDRESSABLE (targ) diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc index 71d7a41374e..4c5375cba9a 100644 --- a/gcc/d/d-convert.cc +++ b/gcc/d/d-convert.cc @@ -694,16 +694,86 @@ convert_for_rvalue (tree expr, Type *etype, Type *totype) return result ? result : convert_expr (expr, etype, totype); } +/* Helper for convert_for_assigment and convert_for_argument. + Returns true if EXPR is a va_list static array parameter. */ + +static bool +is_valist_parameter_type (Expression *expr) +{ + Declaration *decl = NULL; + + if (VarExp *ve = expr->isVarExp ()) + decl = ve->var; + else if (SymOffExp *se = expr->isSymOffExp ()) + decl = se->var; + + if (decl != NULL && decl->isParameter () && valist_array_p (decl->type)) + return true; + + return false; +} + +/* Helper for convert_for_assigment and convert_for_argument. + Report erroneous uses of assigning or passing a va_list parameter. */ + +static void +check_valist_conversion (Expression *expr, Type *totype, bool in_assignment) +{ + /* Parameter symbol and its converted type. */ + Declaration *decl = NULL; + /* Type of parameter when evaluated in the expression. */ + Type *type = NULL; + + if (VarExp *ve = expr->isVarExp ()) + { + decl = ve->var; + type = ve->var->type->nextOf ()->pointerTo (); + } + else if (SymOffExp *se = expr->isSymOffExp ()) + { + decl = se->var; + type = se->var->type->nextOf ()->pointerTo ()->pointerTo (); + } + + /* Should not be called unless is_valist_parameter_type also matched. */ + gcc_assert (decl != NULL && decl->isParameter () + && valist_array_p (decl->type)); + + /* OK if conversion between types is allowed. */ + if (type->implicitConvTo (totype) != MATCH::nomatch) + return; + + if (in_assignment) + { + error_at (make_location_t (expr->loc), "cannot convert parameter %qs " + "from type %qs to type %qs in assignment", + expr->toChars(), type->toChars (), totype->toChars ()); + } + else + { + error_at (make_location_t (expr->loc), "cannot convert parameter %qs " + "from type %qs to type %qs in argument passing", + expr->toChars(), type->toChars (), totype->toChars ()); + } + + inform (make_location_t (decl->loc), "parameters of type % " + "{aka %qs} are decayed to pointer types, and require % " + "to be converted back into a static array type", + decl->type->toChars ()); +} + /* Apply semantics of assignment to a value of type TOTYPE to EXPR - (e.g., pointer = array -> pointer = &array[0]) + For example: `pointer = array' gets lowered to `pointer = &array[0]'. + If LITERALP is true, then EXPR is a value used in the initialization + of another literal. Return a TREE representation of EXPR implicitly converted to TOTYPE for use in assignment expressions MODIFY_EXPR, INIT_EXPR. */ tree -convert_for_assignment (tree expr, Type *etype, Type *totype) +convert_for_assignment (Expression *expr, Type *totype, bool literalp) { - Type *ebtype = etype->toBasetype (); + Type *ebtype = expr->type->toBasetype (); Type *tbtype = totype->toBasetype (); /* Assuming this only has to handle converting a non Tsarray type to @@ -723,8 +793,8 @@ convert_for_assignment (tree expr, Type *etype, Type *totype) vec *ce = NULL; tree index = build2 (RANGE_EXPR, build_ctype (Type::tsize_t), size_zero_node, size_int (count - 1)); - tree value = convert_for_assignment (expr, etype, sa_type->next); - + tree value = convert_for_assignment (expr, sa_type->next, + literalp); /* Can't use VAR_DECLs in CONSTRUCTORS. */ if (VAR_P (value)) { @@ -745,38 +815,53 @@ convert_for_assignment (tree expr, Type *etype, Type *totype) if ((tbtype->ty == TY::Tsarray || tbtype->ty == TY::Tstruct) && ebtype->isintegral ()) { - if (!integer_zerop (expr)) - gcc_unreachable (); - - return expr; + tree ret = build_expr (expr, false, literalp); + gcc_assert (integer_zerop (ret)); + return ret; } - return convert_for_rvalue (expr, etype, totype); + /* Assigning a va_list by value or reference, check whether RHS is a parameter + that has has been lowered by declaration_type or parameter_type. */ + if (is_valist_parameter_type (expr)) + check_valist_conversion (expr, totype, true); + + return convert_for_rvalue (build_expr (expr, false, literalp), + expr->type, totype); } /* Return a TREE representation of EXPR converted to represent the parameter type ARG. */ tree -convert_for_argument (tree expr, Parameter *arg) +convert_for_argument (Expression *expr, Parameter *arg) { + tree targ = build_expr (expr); + /* Lazy arguments: expr should already be a delegate. */ if (arg->storageClass & STClazy) - return expr; + return targ; + /* Passing a va_list by value, check whether the target requires it to + be decayed to a pointer type. */ if (valist_array_p (arg->type)) { - /* Do nothing if the va_list has already been decayed to a pointer. */ - if (!POINTER_TYPE_P (TREE_TYPE (expr))) - return build_address (expr); - } - else if (parameter_reference_p (arg)) - { - /* Front-end shouldn't automatically take the address. */ - return convert (parameter_type (arg), build_address (expr)); + if (!POINTER_TYPE_P (TREE_TYPE (targ))) + return build_address (targ); + + /* Do nothing if the va_list has already been converted. */ + return targ; } - return expr; + /* Passing a va_list by reference, check if types are really compatible + after conversion from static array to pointer type. */ + if (is_valist_parameter_type (expr)) + check_valist_conversion (expr, arg->type, false); + + /* Front-end shouldn't automatically take the address of `ref' parameters. */ + if (parameter_reference_p (arg)) + return convert (parameter_type (arg), build_address (targ)); + + return targ; } /* Perform default promotions for data used in expressions. diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 7763695a106..d19c3f50bd9 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -625,8 +625,8 @@ extern tree d_truthvalue_conversion (tree); extern tree d_convert (tree, tree); extern tree convert_expr (tree, Type *, Type *); extern tree convert_for_rvalue (tree, Type *, Type *); -extern tree convert_for_assignment (tree, Type *, Type *); -extern tree convert_for_argument (tree, Parameter *); +extern tree convert_for_assignment (Expression *, Type *, bool = false); +extern tree convert_for_argument (Expression *, Parameter *); extern tree convert_for_condition (tree, Type *); extern tree d_array_convert (Expression *); extern tree d_array_convert (Type *, Expression *); diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 29f114a1b99..ef4ea60ffed 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -972,8 +972,7 @@ public: Declaration *decl = e->e1->isVarExp ()->var; if (decl->storage_class & (STCout | STCref)) { - tree t2 = convert_for_assignment (build_expr (e->e2), - e->e2->type, e->e1->type); + tree t2 = convert_for_assignment (e->e2, e->e1->type); tree t1 = build_expr (e->e1); /* Want reference to lhs, not indirect ref. */ t1 = TREE_OPERAND (t1, 0); @@ -993,8 +992,7 @@ public: if (tb1->ty == TY::Tstruct) { tree t1 = build_expr (e->e1); - tree t2 = convert_for_assignment (build_expr (e->e2, false, true), - e->e2->type, e->e1->type); + tree t2 = convert_for_assignment (e->e2, e->e1->type, true); StructDeclaration *sd = tb1->isTypeStruct ()->sym; /* Look for struct = 0. */ @@ -1073,8 +1071,7 @@ public: || (e->op == EXP::blit || e->e1->type->size () == 0)) { tree t1 = build_expr (e->e1); - tree t2 = convert_for_assignment (build_expr (e->e2), - e->e2->type, e->e1->type); + tree t2 = convert_for_assignment (e->e2, e->e1->type); this->result_ = build_assign (modifycode, t1, t2); return; @@ -1088,8 +1085,7 @@ public: /* Simple assignment. */ tree t1 = build_expr (e->e1); - tree t2 = convert_for_assignment (build_expr (e->e2), - e->e2->type, e->e1->type); + tree t2 = convert_for_assignment (e->e2, e->e1->type); this->result_ = build_assign (modifycode, t1, t2); } diff --git a/gcc/testsuite/gdc.dg/pr110712.d b/gcc/testsuite/gdc.dg/pr110712.d new file mode 100644 index 00000000000..ed24b6c90cc --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr110712.d @@ -0,0 +1,23 @@ +// { dg-do compile { target { { i?86-*-* x86_64-*-* } && lp64 } } } +import gcc.builtins : va_list = __builtin_va_list; + +void argpass(va_list *ap); + +void pr110712a(va_list ap) +{ + argpass(&ap); // { dg-error "cannot convert parameter" } +} + +void pr110712b(va_list ap) +{ + va_list ap2 = ap; // { dg-error "cannot convert parameter" } +} + +struct pr110712c +{ + this(va_list ap) + { + this.ap = ap; // { dg-error "cannot convert parameter" } + } + va_list ap; +}