From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1873) id 28CDF384F014; Thu, 29 Jul 2021 15:22:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 28CDF384F014 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Iain Buclaw To: gcc-cvs@gcc.gnu.org Subject: [gcc r9-9653] d: Ensure casting from bool results in either 0 or 1 (PR96435) X-Act-Checkin: gcc X-Git-Author: Iain Buclaw X-Git-Refname: refs/heads/releases/gcc-9 X-Git-Oldrev: 64b7e66c1a86cf880a43c0e31375bb74f15562f3 X-Git-Newrev: c848c0ec7fab0c0a220683ad234c8842939941cf Message-Id: <20210729152206.28CDF384F014@sourceware.org> Date: Thu, 29 Jul 2021 15:22:06 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 Jul 2021 15:22:06 -0000 https://gcc.gnu.org/g:c848c0ec7fab0c0a220683ad234c8842939941cf commit r9-9653-gc848c0ec7fab0c0a220683ad234c8842939941cf Author: Iain Buclaw Date: Mon Jul 26 19:28:02 2021 +0200 d: Ensure casting from bool results in either 0 or 1 (PR96435) If casting from bool, the result is either 0 or 1, any other value violates @safe code, so enforce that it is never invalid. PR d/96435 gcc/d/ChangeLog: * d-convert.cc (convert_for_rvalue): New function. * d-tree.h (convert_for_rvalue): Declare. * expr.cc (ExprVisitor::visit (CastExp *)): Use convert_for_rvalue. (build_return_dtor): Likewise. gcc/testsuite/ChangeLog: * gdc.dg/pr96435.d: New test. (cherry picked from commit 5c9b7408dc578cb2ae142a5c1b724c183497bdb2) Diff: --- gcc/d/d-convert.cc | 36 ++++++++++++++++++++++++++++++++++++ gcc/d/d-tree.h | 1 + gcc/d/expr.cc | 13 ++++++++----- gcc/testsuite/gdc.dg/pr96435.d | 21 +++++++++++++++++++++ 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc index 9c2f6b45a44..537324ddb35 100644 --- a/gcc/d/d-convert.cc +++ b/gcc/d/d-convert.cc @@ -601,6 +601,42 @@ convert_expr (tree exp, Type *etype, Type *totype) return result ? result : convert (build_ctype (totype), exp); } +/* Return a TREE represenwation of EXPR, whose type has been converted from + * ETYPE to TOTYPE, and is being used in an rvalue context. */ + +tree +convert_for_rvalue (tree expr, Type *etype, Type *totype) +{ + tree result = NULL_TREE; + + Type *ebtype = etype->toBasetype (); + Type *tbtype = totype->toBasetype (); + + switch (ebtype->ty) + { + case Tbool: + /* If casting from bool, the result is either 0 or 1, any other value + violates @safe code, so enforce that it is never invalid. */ + if (CONSTANT_CLASS_P (expr)) + result = d_truthvalue_conversion (expr); + else + { + /* Reinterpret the boolean as an integer and test the first bit. + The generated code should end up being equivalent to: + *cast(ubyte *)&expr & 1; */ + machine_mode bool_mode = TYPE_MODE (TREE_TYPE (expr)); + tree mtype = lang_hooks.types.type_for_mode (bool_mode, 1); + result = fold_build2 (BIT_AND_EXPR, mtype, + build_vconvert (mtype, expr), + build_one_cst (mtype)); + } + + result = convert (build_ctype (tbtype), result); + break; + } + + return result ? result : convert_expr (expr, etype, totype); +} /* Apply semantics of assignment to a value of type TOTYPE to EXPR (e.g., pointer = array -> pointer = &array[0]) diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 5daba412a4d..ad8e25fa45d 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -578,6 +578,7 @@ extern bool decl_with_nonnull_addr_p (const_tree); 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_condition (tree, Type *); diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 2d981154672..244dd860b7f 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -1435,7 +1435,7 @@ public: if (tbtype->ty == Tvoid) this->result_ = build_nop (build_ctype (tbtype), result); else - this->result_ = convert_expr (result, ebtype, tbtype); + this->result_ = convert_for_rvalue (result, ebtype, tbtype); } /* Build a delete expression. */ @@ -3106,11 +3106,14 @@ build_return_dtor (Expression *e, Type *type, TypeFunction *tf) tree result = build_expr (e); /* Convert for initializing the DECL_RESULT. */ - result = convert_expr (result, e->type, type); - - /* If we are returning a reference, take the address. */ if (tf->isref) - result = build_address (result); + { + /* If we are returning a reference, take the address. */ + result = convert_expr (result, e->type, type); + result = build_address (result); + } + else + result = convert_for_rvalue (result, e->type, type); /* The decl to store the return expression. */ tree decl = DECL_RESULT (cfun->decl); diff --git a/gcc/testsuite/gdc.dg/pr96435.d b/gcc/testsuite/gdc.dg/pr96435.d new file mode 100644 index 00000000000..c6d8785ec5b --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr96435.d @@ -0,0 +1,21 @@ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96435 +// { dg-do run } + +@safe bool test96435() +{ + int[2] array = [16, 678]; + union U { int i; bool b; } + U u; + u.i = 0xDEADBEEF; + assert(array[u.b] == 678); + return u.b; +} + +@safe void main() +{ + auto b = test96435(); + if (b) + assert(true); + if (!b) + assert(false); +}