[clang] Implement -fstrict-bool (#160790)
This PR implements the [-fstrict-bool
RFC](https://discourse.llvm.org/t/defining-what-happens-when-a-bool-isn-t-0-or-1/86778/).
``bool`` values are stored as i8 in memory, and it is undefined behavior
for a ``bool`` value to be any value other than 0 or 1. Clang exploits
this with range metadata: ``bool`` load instructions at any optimization
level above -O0 are assumed to only have their lowest bit set. This can
create memory safety problems when other bits are set, for instance
through ``memcpy``.
This change allows users to configure this behavior in three ways:
* ``-fstrict-bool`` represents the status quo; range metadata is added
at levels above -O0 and allows the compiler to assume in-memory ``bool``
values are always either 0 or 1.
* ``-fno-strict-bool[={truncate|nonzero}]`` disables range metadata on
``bool`` loaded values and offers two ways to interpret the loaded
values. ``truncate`` means the value is true is the least significant
bit is 1 and false otherwise; ``nonzero`` means the value is true if any
bit is 1 and false otherwise.
The default is ``-fstrict-bool`` to not change the current behavior of
Clang. The default behavior of ``-fno-strict-bool`` is ``truncate``.
Radar-ID: 139397212