public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
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>

  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).