aboutsummaryrefslogtreecommitdiff
path: root/gcc/doc
diff options
context:
space:
mode:
authorAlexandre Oliva <oliva@adacore.com>2023-11-29 04:00:45 -0300
committerAlexandre Oliva <oliva@gnu.org>2023-11-29 04:00:45 -0300
commit862867eab78d7731f725cf7fa4ba02ed5e503db1 (patch)
tree8cb72282d503631c52973cc05290aec00fe3a19e /gcc/doc
parent0d24289d129639efdc79338a64188d6d404375e8 (diff)
downloadgcc-862867eab78d7731f725cf7fa4ba02ed5e503db1.zip
gcc-862867eab78d7731f725cf7fa4ba02ed5e503db1.tar.gz
gcc-862867eab78d7731f725cf7fa4ba02ed5e503db1.tar.bz2
Introduce hardbool attribute for C
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. 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. * doc/invoke.texi (-ftrivial-auto-var-init): Document representation vs values. for gcc/testsuite/ChangeLog * gcc.dg/hardbool-err.c: New. * gcc.dg/hardbool-trap.c: New. * gcc.dg/torture/hardbool.c: New. * gcc.dg/torture/hardbool-s.c: New. * gcc.dg/torture/hardbool-us.c: New. * gcc.dg/torture/hardbool-i.c: New. * gcc.dg/torture/hardbool-ul.c: New. * gcc.dg/torture/hardbool-ll.c: New. * gcc.dg/torture/hardbool-5a.c: New. * gcc.dg/torture/hardbool-s-5a.c: New. * gcc.dg/torture/hardbool-us-5a.c: New. * gcc.dg/torture/hardbool-i-5a.c: New. * gcc.dg/torture/hardbool-ul-5a.c: New. * gcc.dg/torture/hardbool-ll-5a.c: New.
Diffstat (limited to 'gcc/doc')
-rw-r--r--gcc/doc/extend.texi65
-rw-r--r--gcc/doc/invoke.texi21
2 files changed, 86 insertions, 0 deletions
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 1ae589a..e6de081 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -8962,6 +8962,71 @@ 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.
+
+Users of @option{-ftrivial-auto-var-init} should be aware that the bit
+patterns used as initializers are @emph{not} converted to
+@code{hardbool} types, so using a @code{hardbool} variable that is
+implicitly initialized by the @option{-ftrivial-auto-var-init} may trap
+if the representations values chosen for @code{false} and @code{true} do
+not match the initializer.
+
+Since this is a language extension only available in C, interoperation
+with other languages may pose difficulties. It should interoperate with
+Ada Booleans defined with the same size and equivalent representation
+clauses, and with enumerations or other languages' integral types that
+correspond to C's chosen integral type.
+
+
@cindex @code{may_alias} type attribute
@item may_alias
Accesses through pointers to types with this attribute are not subject
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9f8a4ef..7e981dc 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13744,6 +13744,27 @@ The values used for pattern initialization might be changed in the future.
The default is @samp{uninitialized}.
+Note that the initializer values, whether @samp{zero} or @samp{pattern},
+refer to data representation (in memory or machine registers), rather
+than to their interpretation as numerical values. This distinction may
+be important in languages that support types with biases or implicit
+multipliers, and with such extensions as @samp{hardbool} (@pxref{Type
+Attributes}). For example, a variable that uses 8 bits to represent
+(biased) quantities in the @code{range 160..400} will be initialized
+with the bit patterns @code{0x00} or @code{0xFE}, depending on
+@var{choice}, whether or not these representations stand for values in
+that range, and even if they do, the interpretation of the value held by
+the variable will depend on the bias. A @samp{hardbool} variable that
+uses say @code{0X5A} and @code{0xA5} for @code{false} and @code{true},
+respectively, will trap with either @samp{choice} of trivial
+initializer, i.e., @samp{zero} initialization will not convert to the
+representation for @code{false}, even if it would for a @code{static}
+variable of the same type. This means the initializer pattern doesn't
+generally depend on the type of the initialized variable. One notable
+exception is that (non-hardened) boolean variables that fit in registers
+are initialized with @code{false} (zero), even when @samp{pattern} is
+requested.
+
You can control this behavior for a specific variable by using the variable
attribute @code{uninitialized} (@pxref{Variable Attributes}).