diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-07-26 19:28:02 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-07-29 16:16:19 +0200 |
commit | 5c9b7408dc578cb2ae142a5c1b724c183497bdb2 (patch) | |
tree | 9d66585f4b9e8f11d44c05275ea7016577471721 /gcc/d/d-convert.cc | |
parent | 75f2e3f6cbbb79421b12e399498e9c14241359e7 (diff) | |
download | gcc-5c9b7408dc578cb2ae142a5c1b724c183497bdb2.zip gcc-5c9b7408dc578cb2ae142a5c1b724c183497bdb2.tar.gz gcc-5c9b7408dc578cb2ae142a5c1b724c183497bdb2.tar.bz2 |
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/torture/pr96435.d: New test.
Diffstat (limited to 'gcc/d/d-convert.cc')
-rw-r--r-- | gcc/d/d-convert.cc | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc index 237c084..d43485d 100644 --- a/gcc/d/d-convert.cc +++ b/gcc/d/d-convert.cc @@ -602,6 +602,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]) |