Hi, Alexandre, > > diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc > index 22e240a3c2a55..f9cc609b54d94 100644 > --- a/gcc/c/c-typeck.cc > +++ b/gcc/c/c-typeck.cc > @@ -2226,6 +2226,35 @@ convert_lvalue_to_rvalue (location_t loc, struct > c_expr exp, > exp.value = convert (build_qualified_type (TREE_TYPE (exp.value), > TYPE_UNQUALIFIED), exp.value); > if (force_non_npc) > exp.value = build1 (NOP_EXPR, TREE_TYPE (exp.value), 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; > + } > + }
I see that you have testing case to check the above built_in_trap call is generated by FE. Do you have a testing case to check the trap is happening at runtime? > + > return exp; > } > > @@ -8488,7 +8517,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 2de212c8c2d84..7b5592502734e 100644 > --- a/gcc/doc/extend.texi > +++ b/gcc/doc/extend.texi > @@ -8681,6 +8681,58 @@ initialization will result in future breakage. > GCC emits warnings based on this attribute by default; use > @option{-Wno-designated-init} to suppress them. > > +@cindex @code{hardbool} type attribute > +@item hardbool > +@itemx hardbool (@var{false_value}) > +@itemx hardbool (@var{false_value}, @var{true_value}) > +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. */ > + > +static hbool zeroinit; /* False, stored as (char)0x5a. */ > +auto hbool uninit; /* Undefined, may trap. */ > +@end smallexample > + > +When zero-initializing a variable or field of hardened boolean type > +(presumably held in static storage) the implied zero initializer gets > +converted to @code{_Bool}, and then to the hardened boolean type, so > +that the initial value is the hardened representation for @code{false}. > +Using that value is well defined. This is @emph{not} the case when > +variables and fields of such types are uninitialized (presumably held in > +automatic or dynamic storage): their values are indeterminate, and using > +them invokes undefined behavior. Using them may trap or not, depending > +on the bits held in the storage (re)used for the variable, if any, and > +on optimizations the compiler may perform on the grounds that using > +uninitialized values invokes undefined behavior. So, when -ftrivial-auto-var-init presents, what’s the behavior for the hardened Boolean auto variables? This might need to be documented and also handled correctly. thanks. Qing