From: Richard Biener <richard.guenther@gmail.com>
To: Alexandre Oliva <oliva@adacore.com>
Cc: GCC Patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] Introduce hardbool attribute for C
Date: Fri, 8 Jul 2022 08:58:34 +0200 [thread overview]
Message-ID: <CAFiYyc3NFmmipnVOYxL0=8RWvtkX3ziPnjBzYbuu07bnoy93Bg@mail.gmail.com> (raw)
In-Reply-To: <orlet4lmn8.fsf@lxoliva.fsfla.org>
On Thu, Jul 7, 2022 at 10:00 PM Alexandre Oliva via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
>
> This patch introduces hardened booleans in C. The hardbool attribute,
> when attached to an integral type, turns it into an enumerate type
> with boolean semantics, using the named or implied constants as
> representations for false and true.
>
> Expressions of such types decay to _Bool, trapping if the value is
> neither true nor false, and _Bool can convert implicitly back to them.
> Other conversions go through _Bool first.
>
> Regstrapped on x86_64-linux-gnu. Ok to install?
Does this follow some other compilers / language? Is such feature used
in existing code? Why is it useful to allow arbitrary values for true/false?
Why is the default 0 and ~0 rather than 0 and 1 as for _Bool?
When writing
> +@smallexample
> +typedef char __attribute__ ((__hardbool__ (0x5a))) hbool;
> +hbool first = 0; /* False, stored as (char)0x5a. */
> +hbool second = !first; /* True, stored as ~(char)0x5a. */
hbool thrid;
what's the initial value of 'third'? Does "zero-initialization" mean
initialization to the corresponding False value (0x5a) or does it
initialize to a zero representation and thus have indeterminate state?
The documentation should probably be explicit about this case.
If the underlying representation is an Enum, why not have hardened_enum
instead? A hardened _Bool might want to have a special NaT value as
well I guess?
Richard.
> for gcc/c-family/ChangeLog
>
> * c-attribs.cc (c_common_attribute_table): Add hardbool.
> (handle_hardbool_attribute): New.
> (type_valid_for_vector_size): Reject hardbool.
> * c-common.cc (convert_and_check): Skip warnings for convert
> and check for hardbool.
> (c_hardbool_type_attr_1): New.
> * c-common.h (c_hardbool_type_attr): New.
>
> for gcc/c/ChangeLog
>
> * c-typeck.cc (convert_lvalue_to_rvalue): Decay hardbools.
> * c-convert.cc (convert): Convert to hardbool through
> truthvalue.
> * c-decl.cc (check_bitfield_type_and_width): Skip enumeral
> truncation warnings for hardbool.
> (finish_struct): Propagate hardbool attribute to bitfield
> types.
> (digest_init): Convert to hardbool.
>
> for gcc/ChangeLog
>
> * doc/extend.texi (hardbool): New type attribute.
>
> for gcc/testsuite/ChangeLog
>
> * gcc.dg/hardbool-err.c: New.
> * gcc.dg/hardbool-trap.c: New.
> * gcc.dg/hardbool.c: New.
> * gcc.dg/hardbool-s.c: New.
> * gcc.dg/hardbool-us.c: New.
> * gcc.dg/hardbool-i.c: New.
> * gcc.dg/hardbool-ul.c: New.
> * gcc.dg/hardbool-ll.c: New.
> * gcc.dg/hardbool-5a.c: New.
> * gcc.dg/hardbool-s-5a.c: New.
> * gcc.dg/hardbool-us-5a.c: New.
> * gcc.dg/hardbool-i-5a.c: New.
> * gcc.dg/hardbool-ul-5a.c: New.
> * gcc.dg/hardbool-ll-5a.c: New.
> ---
> gcc/c-family/c-attribs.cc | 97 ++++++++++++++++++++-
> gcc/c-family/c-common.cc | 21 ++++
> gcc/c-family/c-common.h | 18 ++++
> gcc/c/c-convert.cc | 14 +++
> gcc/c/c-decl.cc | 10 ++
> gcc/c/c-typeck.cc | 31 ++++++-
> gcc/doc/extend.texi | 37 ++++++++
> gcc/testsuite/gcc.dg/hardbool-err.c | 28 ++++++
> gcc/testsuite/gcc.dg/hardbool-trap.c | 13 +++
> gcc/testsuite/gcc.dg/torture/hardbool-5a.c | 6 +
> gcc/testsuite/gcc.dg/torture/hardbool-i-5a.c | 6 +
> gcc/testsuite/gcc.dg/torture/hardbool-i.c | 5 +
> gcc/testsuite/gcc.dg/torture/hardbool-ll-5a.c | 6 +
> gcc/testsuite/gcc.dg/torture/hardbool-ll.c | 5 +
> gcc/testsuite/gcc.dg/torture/hardbool-s-5a.c | 6 +
> gcc/testsuite/gcc.dg/torture/hardbool-s.c | 5 +
> gcc/testsuite/gcc.dg/torture/hardbool-ul-5a.c | 6 +
> gcc/testsuite/gcc.dg/torture/hardbool-ul.c | 5 +
> gcc/testsuite/gcc.dg/torture/hardbool-us-5a.c | 6 +
> gcc/testsuite/gcc.dg/torture/hardbool-us.c | 5 +
> gcc/testsuite/gcc.dg/torture/hardbool.c | 118 +++++++++++++++++++++++++
> 21 files changed, 444 insertions(+), 4 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/hardbool-err.c
> create mode 100644 gcc/testsuite/gcc.dg/hardbool-trap.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-5a.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-i-5a.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-i.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-ll-5a.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-ll.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-s-5a.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-s.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-ul-5a.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-ul.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-us-5a.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool-us.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/hardbool.c
>
> diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
> index c8d96723f4c30..e385d780c49ce 100644
> --- a/gcc/c-family/c-attribs.cc
> +++ b/gcc/c-family/c-attribs.cc
> @@ -172,6 +172,7 @@ static tree handle_objc_root_class_attribute (tree *, tree, tree, int, bool *);
> static tree handle_objc_nullability_attribute (tree *, tree, tree, int, bool *);
> static tree handle_signed_bool_precision_attribute (tree *, tree, tree, int,
> bool *);
> +static tree handle_hardbool_attribute (tree *, tree, tree, int, bool *);
> static tree handle_retain_attribute (tree *, tree, tree, int, bool *);
>
> /* Helper to define attribute exclusions. */
> @@ -288,6 +289,8 @@ const struct attribute_spec c_common_attribute_table[] =
> affects_type_identity, handler, exclude } */
> { "signed_bool_precision", 1, 1, false, true, false, true,
> handle_signed_bool_precision_attribute, NULL },
> + { "hardbool", 0, 2, false, true, false, true,
> + handle_hardbool_attribute, NULL },
> { "packed", 0, 0, false, false, false, false,
> handle_packed_attribute,
> attr_aligned_exclusions },
> @@ -975,6 +978,95 @@ handle_signed_bool_precision_attribute (tree *node, tree name, tree args,
> return NULL_TREE;
> }
>
> +/* Handle a "hardbool" attribute; arguments as in struct
> + attribute_spec.handler. */
> +
> +static tree
> +handle_hardbool_attribute (tree *node, tree name, tree args,
> + int /* flags */, bool *no_add_attrs)
> +{
> + if (c_language != clk_c)
> + {
> + error ("%qE attribute only supported in C", name);
> + *no_add_attrs = TRUE;
> + return NULL_TREE;
> + }
> +
> + if (!TYPE_P (*node) || TREE_CODE (*node) != INTEGER_TYPE)
> + {
> + error ("%qE attribute only supported on "
> + "integral types", name);
> + *no_add_attrs = TRUE;
> + return NULL_TREE;
> + }
> +
> + tree orig = *node;
> + *node = build_duplicate_type (orig);
> +
> + TREE_SET_CODE (*node, ENUMERAL_TYPE);
> +
> + tree false_value;
> + if (args)
> + false_value = fold_convert (*node, TREE_VALUE (args));
> + else
> + false_value = fold_convert (*node, integer_zero_node);
> +
> + if (TREE_OVERFLOW_P (false_value))
> + {
> + warning (OPT_Wattributes,
> + "overflows in conversion from %qT to %qT "
> + "changes value from %qE to %qE",
> + TREE_TYPE (TREE_VALUE (args)), *node,
> + TREE_VALUE (args), false_value);
> + TREE_OVERFLOW (false_value) = false;
> + }
> +
> + tree true_value;
> + if (args && TREE_CHAIN (args))
> + true_value = fold_convert (*node, TREE_VALUE (TREE_CHAIN (args)));
> + else
> + true_value = fold_build1 (BIT_NOT_EXPR, *node, false_value);
> +
> + if (TREE_OVERFLOW_P (true_value))
> + {
> + warning (OPT_Wattributes,
> + "overflows in conversion from %qT to %qT "
> + "changes value from %qE to %qE",
> + TREE_TYPE (TREE_VALUE (TREE_CHAIN (args))), *node,
> + TREE_VALUE (TREE_CHAIN (args)), true_value);
> + TREE_OVERFLOW (true_value) = false;
> + }
> +
> + if (tree_int_cst_compare (false_value, true_value) == 0)
> + {
> + error ("%qE attribute requires different values for"
> + " %<false%> and %<true%> for type %qT",
> + name, *node);
> + *no_add_attrs = TRUE;
> + return NULL_TREE;
> + }
> +
> + tree values = build_tree_list (get_identifier ("false"),
> + false_value);
> + TREE_CHAIN (values) = build_tree_list (get_identifier ("true"),
> + true_value);
> +
> + /* Do *not* set TYPE_MIN_VALUE, TYPE_MAX_VALUE, nor TYPE_PRECISION according
> + to the false and true values. That might cause the constants to be the
> + only acceptable values, which would drop the very hardening checks this
> + attribute is supposed to add. */
> +
> + TYPE_ATTRIBUTES (*node) = tree_cons (name, args,
> + TYPE_ATTRIBUTES (*node));
> + *no_add_attrs = TRUE;
> +
> + gcc_checking_assert (!TYPE_CACHED_VALUES_P (*node));
> + TYPE_VALUES (*node) = values;
> + TYPE_NAME (*node) = orig;
> +
> + return NULL_TREE;
> +}
> +
> /* Handle a "packed" attribute; arguments as in
> struct attribute_spec.handler. */
>
> @@ -4289,7 +4381,8 @@ static tree
> type_valid_for_vector_size (tree type, tree atname, tree args,
> unsigned HOST_WIDE_INT *ptrnunits)
> {
> - bool error_p = ptrnunits != NULL;
> + bool hardbool_p = c_hardbool_type_attr (type);
> + bool error_p = ptrnunits != NULL || hardbool_p;
>
> /* Get the mode of the type being modified. */
> machine_mode orig_mode = TYPE_MODE (type);
> @@ -4301,7 +4394,7 @@ type_valid_for_vector_size (tree type, tree atname, tree args,
> && GET_MODE_CLASS (orig_mode) != MODE_INT
> && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
> || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
> - || TREE_CODE (type) == BOOLEAN_TYPE)
> + || TREE_CODE (type) == BOOLEAN_TYPE || hardbool_p)
> {
> if (error_p)
> error ("invalid vector type for attribute %qE", atname);
> diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
> index 1b8e73f7bc5d8..9a8584a5fe095 100644
> --- a/gcc/c-family/c-common.cc
> +++ b/gcc/c-family/c-common.cc
> @@ -1780,7 +1780,8 @@ convert_and_check (location_t loc, tree type, tree expr, bool init_const)
>
> if (c_inhibit_evaluation_warnings == 0
> && !TREE_OVERFLOW_P (expr)
> - && result != error_mark_node)
> + && result != error_mark_node
> + && !c_hardbool_type_attr (type))
> warnings_for_convert_and_check (loc, type, expr_for_warning, result);
>
> return result;
> @@ -9488,4 +9489,22 @@ c_common_finalize_early_debug (void)
> (*debug_hooks->early_global_decl) (cnode->decl);
> }
>
> +/* This is the slow path of c-common.h's c_hardbool_type_attr. */
> +
> +tree
> +c_hardbool_type_attr_1 (tree type, tree *false_value, tree *true_value)
> +{
> + tree attr = lookup_attribute ("hardbool", TYPE_ATTRIBUTES (type));
> + if (!attr)
> + return attr;
> +
> + if (false_value)
> + *false_value = TREE_VALUE (TYPE_VALUES (type));
> +
> + if (true_value)
> + *true_value = TREE_VALUE (TREE_CHAIN (TYPE_VALUES (type)));
> +
> + return attr;
> +}
> +
> #include "gt-c-family-c-common.h"
> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> index c0900848965a3..a8d6691d0813d 100644
> --- a/gcc/c-family/c-common.h
> +++ b/gcc/c-family/c-common.h
> @@ -912,6 +912,7 @@ extern tree c_common_get_narrower (tree, int *);
> extern bool get_attribute_operand (tree, unsigned HOST_WIDE_INT *);
> extern void c_common_finalize_early_debug (void);
> extern bool c_option_is_from_cpp_diagnostics (int);
> +extern tree c_hardbool_type_attr_1 (tree, tree *, tree *);
>
> /* Used by convert_and_check; in front ends. */
> extern tree convert_init (tree, tree);
> @@ -1291,6 +1292,23 @@ c_tree_chain_next (tree t)
> return NULL;
> }
>
> +/* Return the hardbool attribute associated with TYPE, if there is one, provided
> + that TYPE looks like an enumeral type that might have been set up by
> + handle_hardbool_attribute. Return NULL otherwise.
> +
> + If FALSE_VALUE or TRUE_VALUE are non-NULL and TYPE is a hardened boolean
> + type, store the corresponding representation values. */
> +static inline tree
> +c_hardbool_type_attr (tree type,
> + tree *false_value = NULL, tree *true_value = NULL)
> +{
> + if (TREE_CODE (type) != ENUMERAL_TYPE
> + || TYPE_LANG_SPECIFIC (type))
> + return NULL_TREE;
> +
> + return c_hardbool_type_attr_1 (type, false_value, true_value);
> +}
> +
> /* Mask used by tm_stmt_attr. */
> #define TM_STMT_ATTR_OUTER 2
> #define TM_STMT_ATTR_ATOMIC 4
> diff --git a/gcc/c/c-convert.cc b/gcc/c/c-convert.cc
> index 18083d5961826..1399cbf9d8d37 100644
> --- a/gcc/c/c-convert.cc
> +++ b/gcc/c/c-convert.cc
> @@ -105,6 +105,20 @@ c_convert (tree type, tree expr, bool init_const)
> return error_mark_node;
> }
>
> + {
> + tree false_value, true_value;
> + if (c_hardbool_type_attr (type, &false_value, &true_value))
> + {
> + bool save = in_late_binary_op;
> + in_late_binary_op = true;
> + expr = c_objc_common_truthvalue_conversion (input_location, expr);
> + in_late_binary_op = save;
> +
> + return fold_build3_loc (loc, COND_EXPR, type,
> + expr, true_value, false_value);
> + }
> + }
> +
> switch (code)
> {
> case VOID_TYPE:
> diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
> index ae8990c138fd2..e103582d677cd 100644
> --- a/gcc/c/c-decl.cc
> +++ b/gcc/c/c-decl.cc
> @@ -6163,6 +6163,12 @@ check_bitfield_type_and_width (location_t loc, tree *type, tree *width,
> else
> w = tree_to_uhwi (*width);
>
> + /* Truncation of hardbool false and true representation values is always safe:
> + either the values remain different, or we'll report a problem when creating
> + the narrower type. */
> + if (c_hardbool_type_attr (*type))
> + return;
> +
> if (TREE_CODE (*type) == ENUMERAL_TYPE)
> {
> struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
> @@ -8887,6 +8893,10 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
> {
> TREE_TYPE (field)
> = c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
> + if (tree attr = c_hardbool_type_attr (type))
> + decl_attributes (&TREE_TYPE (field),
> + copy_list (attr),
> + 0, NULL_TREE);
> SET_DECL_MODE (field, TYPE_MODE (TREE_TYPE (field)));
> }
> DECL_INITIAL (field) = NULL_TREE;
> diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
> index fd0a7f81a7a92..1244241dd295b 100644
> --- a/gcc/c/c-typeck.cc
> +++ b/gcc/c/c-typeck.cc
> @@ -2172,6 +2172,35 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
> if (convert_p && !error_operand_p (exp.value)
> && (TREE_CODE (TREE_TYPE (exp.value)) != ARRAY_TYPE))
> exp.value = convert (build_qualified_type (TREE_TYPE (exp.value), TYPE_UNQUALIFIED), exp.value);
> +
> + {
> + tree false_value, true_value;
> + if (convert_p && !error_operand_p (exp.value)
> + && c_hardbool_type_attr (TREE_TYPE (exp.value),
> + &false_value, &true_value))
> + {
> + tree t = save_expr (exp.value);
> +
> + mark_exp_read (exp.value);
> +
> + tree trapfn = builtin_decl_explicit (BUILT_IN_TRAP);
> + tree expr = build_call_expr_loc (loc, trapfn, 0);
> + expr = build_compound_expr (loc, expr, boolean_true_node);
> + expr = fold_build3_loc (loc, COND_EXPR, boolean_type_node,
> + fold_build2_loc (loc, NE_EXPR,
> + boolean_type_node,
> + t, true_value),
> + expr, boolean_true_node);
> + expr = fold_build3_loc (loc, COND_EXPR, boolean_type_node,
> + fold_build2_loc (loc, NE_EXPR,
> + boolean_type_node,
> + t, false_value),
> + expr, boolean_false_node);
> +
> + exp.value = expr;
> + }
> + }
> +
> return exp;
> }
>
> @@ -8167,7 +8196,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
> }
> }
>
> - if (code == VECTOR_TYPE)
> + if (code == VECTOR_TYPE || c_hardbool_type_attr (type))
> /* Although the types are compatible, we may require a
> conversion. */
> inside_init = convert (type, inside_init);
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index dfbe33ac652f8..7b514354263f4 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -8654,6 +8654,43 @@ initialization will result in future breakage.
> GCC emits warnings based on this attribute by default; use
> @option{-Wno-designated-init} to suppress them.
>
> +@item hardbool
> +@itemx hardbool (@var{false_value})
> +@itemx hardbool (@var{false_value}, @var{true_value})
> +@cindex @code{hardbool} type attribute
> +This attribute may only be applied to integral types in C, to introduce
> +hardened boolean types. It turns the integral type into a boolean-like
> +type with the same size and precision, that uses the specified values as
> +representations for @code{false} and @code{true}. Underneath, it is
> +actually an enumerate type, but its observable behavior is like that of
> +@code{_Bool}, except for the strict internal representations, verified
> +by runtime checks.
> +
> +If @var{true_value} is omitted, the bitwise negation of
> +@var{false_value} is used. If @var{false_value} is omitted, zero is
> +used. The named representation values must be different when converted
> +to the original integral type. Narrower bitfields are rejected if the
> +representations become indistinguishable.
> +
> +Values of such types automatically decay to @code{_Bool}, at which
> +point, the selected representation values are mapped to the
> +corresponding @code{_Bool} values. When the represented value is not
> +determined, at compile time, to be either @var{false_value} or
> +@var{true_value}, runtime verification calls @code{__builtin_trap} if it
> +is neither. This is what makes them hardened boolean types.
> +
> +When converting scalar types to such hardened boolean types, implicitly
> +or explicitly, behavior corresponds to a conversion to @code{_Bool},
> +followed by a mapping from @code{false} and @code{true} to
> +@var{false_value} and @var{true_value}, respectively.
> +
> +@smallexample
> +typedef char __attribute__ ((__hardbool__ (0x5a))) hbool;
> +hbool first = 0; /* False, stored as (char)0x5a. */
> +hbool second = !first; /* True, stored as ~(char)0x5a. */
> +@end smallexample
> +
> +
> @item may_alias
> @cindex @code{may_alias} type attribute
> Accesses through pointers to types with this attribute are not subject
> diff --git a/gcc/testsuite/gcc.dg/hardbool-err.c b/gcc/testsuite/gcc.dg/hardbool-err.c
> new file mode 100644
> index 0000000000000..634feaed4deef
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/hardbool-err.c
> @@ -0,0 +1,28 @@
> +/* { dg-do compile } */
> +/* { dg-options "" } */
> +
> +typedef _Bool __attribute__ ((__hardbool__))
> +hbbl; /* { dg-error "integral types" } */
> +
> +typedef double __attribute__ ((__hardbool__))
> +hbdbl; /* { dg-error "integral types" } */
> +
> +enum x;
> +typedef enum x __attribute__ ((__hardbool__))
> +hbenum; /* { dg-error "integral types" } */
> +
> +struct s;
> +typedef struct s __attribute__ ((__hardbool__))
> +hbstruct; /* { dg-error "integral types" } */
> +
> +typedef int __attribute__ ((__hardbool__ (0, 0)))
> +hb00; /* { dg-error "different values" } */
> +
> +typedef int __attribute__ ((__hardbool__ (4, 16))) hb4x;
> +struct s {
> + hb4x m:2;
> +}; /* { dg-error "is a GCC extension|different values" } */
> +/* { dg-warning "changes value" "warning" { target *-*-* } .-1 } */
> +
> +hb4x __attribute__ ((vector_size (4 * sizeof (hb4x))))
> +vvar; /* { dg-error "invalid vector type" } */
> diff --git a/gcc/testsuite/gcc.dg/hardbool-trap.c b/gcc/testsuite/gcc.dg/hardbool-trap.c
> new file mode 100644
> index 0000000000000..2eebd0ef64fff
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/hardbool-trap.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fdump-tree-optimized" } */
> +
> +typedef char __attribute__ ((__hardbool__ (1))) hbool;
> +
> +hbool var;
> +
> +int main () {
> + __builtin_memset (&var, 0, sizeof (var));
> + (void)var;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "__builtin_trap" 1 "optimized" } } */
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-5a.c b/gcc/testsuite/gcc.dg/torture/hardbool-5a.c
> new file mode 100644
> index 0000000000000..a03887cfbecc5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-5a.c
> @@ -0,0 +1,6 @@
> +/* { dg-do run } */
> +/* { dg-options "-w" } */
> +
> +#define falseval 0x5a
> +
> +#include "hardbool.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-i-5a.c b/gcc/testsuite/gcc.dg/torture/hardbool-i-5a.c
> new file mode 100644
> index 0000000000000..c0ba2a8b9148e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-i-5a.c
> @@ -0,0 +1,6 @@
> +/* { dg-do run } */
> +/* { dg-options "-w" } */
> +
> +#define falseval 0xa53cc35a
> +
> +#include "hardbool-i.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-i.c b/gcc/testsuite/gcc.dg/torture/hardbool-i.c
> new file mode 100644
> index 0000000000000..39214d28c5627
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-i.c
> @@ -0,0 +1,5 @@
> +/* { dg-do run } */
> +
> +#define basetype int
> +
> +#include "hardbool.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-ll-5a.c b/gcc/testsuite/gcc.dg/torture/hardbool-ll-5a.c
> new file mode 100644
> index 0000000000000..14438c5104f07
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-ll-5a.c
> @@ -0,0 +1,6 @@
> +/* { dg-do run } */
> +/* { dg-options "-w" } */
> +
> +#define falseval 0x781ee187a53cc35all
> +
> +#include "hardbool-ll.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-ll.c b/gcc/testsuite/gcc.dg/torture/hardbool-ll.c
> new file mode 100644
> index 0000000000000..d4d498c6f2af1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-ll.c
> @@ -0,0 +1,5 @@
> +/* { dg-do run } */
> +
> +#define basetype long long
> +
> +#include "hardbool.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-s-5a.c b/gcc/testsuite/gcc.dg/torture/hardbool-s-5a.c
> new file mode 100644
> index 0000000000000..e38a56b5deb05
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-s-5a.c
> @@ -0,0 +1,6 @@
> +/* { dg-do run } */
> +/* { dg-options "-w" } */
> +
> +#define falseval 0x5aa5
> +
> +#include "hardbool-s.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-s.c b/gcc/testsuite/gcc.dg/torture/hardbool-s.c
> new file mode 100644
> index 0000000000000..942300be2072a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-s.c
> @@ -0,0 +1,5 @@
> +/* { dg-do run } */
> +
> +#define basetype short
> +
> +#include "hardbool.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-ul-5a.c b/gcc/testsuite/gcc.dg/torture/hardbool-ul-5a.c
> new file mode 100644
> index 0000000000000..7beec578ff89c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-ul-5a.c
> @@ -0,0 +1,6 @@
> +/* { dg-do run } */
> +/* { dg-options "-w" } */
> +
> +#define falseval 0xa53cc35a
> +
> +#include "hardbool-ul.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-ul.c b/gcc/testsuite/gcc.dg/torture/hardbool-ul.c
> new file mode 100644
> index 0000000000000..841c1d4bc2ec8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-ul.c
> @@ -0,0 +1,5 @@
> +/* { dg-do run } */
> +
> +#define basetype unsigned long
> +
> +#include "hardbool.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-us-5a.c b/gcc/testsuite/gcc.dg/torture/hardbool-us-5a.c
> new file mode 100644
> index 0000000000000..5bfc922795d3d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-us-5a.c
> @@ -0,0 +1,6 @@
> +/* { dg-do run } */
> +/* { dg-options "-w" } */
> +
> +#define falseval 0xa55a
> +
> +#include "hardbool-us.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-us.c b/gcc/testsuite/gcc.dg/torture/hardbool-us.c
> new file mode 100644
> index 0000000000000..e9feec681c41e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool-us.c
> @@ -0,0 +1,5 @@
> +/* { dg-do run } */
> +
> +#define basetype unsigned short
> +
> +#include "hardbool.c"
> diff --git a/gcc/testsuite/gcc.dg/torture/hardbool.c b/gcc/testsuite/gcc.dg/torture/hardbool.c
> new file mode 100644
> index 0000000000000..01684952a2a9f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/hardbool.c
> @@ -0,0 +1,118 @@
> +/* { dg-do run } */
> +
> +#include <assert.h>
> +
> +#ifndef basetype
> +#define basetype char
> +#endif
> +
> +#ifndef falseval
> +#define falseval 0
> +#endif
> +
> +#ifndef trueval
> +#define trueval ~falseval
> +#endif
> +
> +/* hardbool may be #defined so as to drop parms in other tests. */
> +typedef basetype __attribute__ ((hardbool (falseval, trueval))) hbool;
> +
> +typedef unsigned char __attribute__ ((__hardbool__ (1, 0))) zbool;
> +
> +struct hs {
> + hbool a[2];
> + hbool x:2;
> + hbool y:5;
> + zbool z:1;
> +};
> +
> +hbool var = 0;
> +
> +struct hs x = { { 1, 0 }, 2, 0, 2 };
> +
> +int f(hbool v) {
> + return !v;
> +}
> +
> +int g(int i) {
> + return f(i);
> +}
> +
> +hbool h(hbool x) {
> + return x;
> +}
> +
> +hbool h2(hbool x) {
> + return h(x);
> +}
> +
> +int hsx(struct hs v) {
> + return v.x;
> +}
> +
> +int ghs(hbool s) {
> + struct hs v = { {s, !s}, s, !s, s };
> + return hsx (v);
> +}
> +
> +int t = (hbool)2;
> +
> +void check_pfalse (hbool *p)
> +{
> + assert (!*p);
> + assert (*(basetype*)p == (basetype)falseval);
> + assert (!(int)(hbool)*p);
> +}
> +
> +void check_ptrue (hbool *p)
> +{
> + assert (*p);
> + assert (*(basetype*)p == (basetype)trueval);
> + assert ((int)(hbool)*p);
> +}
> +
> +void check_vfalse (hbool v)
> +{
> + check_pfalse (&v);
> +}
> +
> +void check_vtrue (hbool v)
> +{
> + check_ptrue (&v);
> +}
> +
> +int main () {
> + check_pfalse (&var);
> + var = !(int)(hbool)(_Bool)var;
> + check_ptrue (&var);
> + var = (zbool)var;
> + check_ptrue (&var);
> +
> + check_ptrue (&x.a[0]);
> + check_pfalse (&x.a[1]);
> + check_vtrue (x.x);
> + check_vfalse (x.y);
> + check_vtrue (x.z);
> +
> + check_vtrue (t);
> +
> + check_vtrue (var && t);
> + check_vfalse (!var || x.y);
> +
> + check_vfalse (f (2));
> + check_vfalse (f (1));
> + check_vtrue (f (0));
> +
> + check_vfalse (g (2));
> + check_vfalse (g (1));
> + check_vtrue (g (0));
> +
> + check_vtrue (h (2));
> + check_vtrue (h (1));
> + check_vfalse (h (0));
> +
> + check_vtrue (h2 (2));
> + check_vtrue (h2 (1));
> + check_vfalse (h2 (0));
> +}
> +
>
>
> --
> Alexandre Oliva, happy hacker https://FSFLA.org/blogs/lxo/
> Free Software Activist GNU Toolchain Engineer
> Disinformation flourishes because many people care deeply about injustice
> but very few check the facts. Ask me about <https://stallmansupport.org>
next prev parent reply other threads:[~2022-07-08 6:58 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-07 19:59 Alexandre Oliva
2022-07-08 6:58 ` Richard Biener [this message]
2022-07-08 13:39 ` Sebastian Huber
2022-07-08 15:28 ` Alexandre Oliva
2022-07-08 15:28 ` Alexandre Oliva
2022-07-11 9:59 ` Richard Biener
2022-08-09 13:53 ` Alexandre Oliva
2023-06-16 5:35 ` Alexandre Oliva
2023-06-19 18:48 ` Bernhard Reutner-Fischer
2023-06-22 1:08 ` Alexandre Oliva
2023-06-22 21:15 ` Bernhard Reutner-Fischer
2023-06-24 2:57 ` Alexandre Oliva
2023-06-21 15:57 ` Qing Zhao
2023-06-22 2:35 ` Alexandre Oliva
2023-06-23 21:40 ` Qing Zhao
2023-06-24 2:38 ` Alexandre Oliva
2023-06-26 19:05 ` Qing Zhao
2023-06-28 7:26 ` Alexandre Oliva
2023-06-28 15:07 ` Qing Zhao
2023-06-29 10:30 ` Alexandre Oliva
2023-06-29 15:21 ` Qing Zhao
2023-06-24 4:42 ` Alexandre Oliva
2023-10-20 5:31 ` [PATCH v4] " Alexandre Oliva
2023-11-20 12:45 ` Alexandre Oliva
2023-11-20 13:56 ` Richard Biener
2023-11-29 9:30 ` Alexandre Oliva
[not found] ` <20230403012803.29ccf00b@nbbrfq>
[not found] ` <orzg7l8rr4.fsf@lxoliva.fsfla.org>
[not found] ` <6890D6BA-73DC-4F91-9413-228492A7F09B@gmail.com>
[not found] ` <ora5x0x8x9.fsf@lxoliva.fsfla.org>
2023-06-16 6:52 ` [PATCH] " Thomas Koenig
2023-06-16 8:03 ` Alexandre Oliva
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAFiYyc3NFmmipnVOYxL0=8RWvtkX3ziPnjBzYbuu07bnoy93Bg@mail.gmail.com' \
--to=richard.guenther@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=oliva@adacore.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).