@@ -8415,3 +8415,71 @@ of ``nonallocating`` by the compiler.
84158415 }];
84168416}
84178417
8418+ def WrapsDocs : Documentation {
8419+ let Category = DocCatField;
8420+ let Content = [{
8421+ This attribute can be used with type or variable declarations to denote that
8422+ arithmetic containing these marked components have defined overflow behavior.
8423+ Specifically, the behavior is defined as being consistent with two's complement
8424+ wrap-around. For the purposes of sanitizers or warnings that concern themselves
8425+ with the definedness of integer arithmetic, they will cease to instrument or
8426+ warn about arithmetic that directly involves a "wrapping" component.
8427+
8428+ For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
8429+ will not warn about suspicious overflowing arithmetic -- assuming correct usage
8430+ of the wraps attribute.
8431+
8432+ This example shows some basic usage of ``__attribute__((wraps))`` on a type
8433+ definition when building with ``-fsanitize=signed-integer-overflow``
8434+
8435+ .. code-block:: c
8436+
8437+ typedef int __attribute__((wraps)) wrapping_int;
8438+
8439+ void foo() {
8440+ wrapping_int a = INT_MAX;
8441+ ++a; // no sanitizer warning
8442+ }
8443+
8444+ int main() { foo(); }
8445+
8446+ In the following example, we use ``__attribute__((wraps))`` on a variable to
8447+ disable overflow instrumentation for arithmetic expressions it appears in. We
8448+ do so with a popular overflow-checking pattern which we might not want to trip
8449+ sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
8450+
8451+ .. code-block:: c
8452+
8453+ void foo(int offset) {
8454+ unsigned int A __attribute__((wraps)) = UINT_MAX;
8455+
8456+ // check for overflow using a common pattern, however we may accidentally
8457+ // perform a real overflow thus triggering sanitizers to step in. Since "A"
8458+ // is "wrapping", we can avoid sanitizer warnings.
8459+ if (A + offset < A) {
8460+ // handle overflow manually
8461+ // ...
8462+ return;
8463+ }
8464+
8465+ // now, handle non-overflow case ...
8466+ }
8467+
8468+ The above example demonstrates some of the power and elegance this attribute
8469+ provides. We can use code patterns we are already familiar with (like ``if (x +
8470+ y < x)``) while gaining control over the overflow behavior on a case-by-case
8471+ basis.
8472+
8473+ When combined with ``-fwrapv``, this attribute can still be applied as normal
8474+ but has no function apart from annotating types and variables for readers. This
8475+ is because ``-fwrapv`` defines all arithmetic as being "wrapping", rendering
8476+ this attribute's efforts redundant.
8477+
8478+ When using this attribute without ``-fwrapv`` and without any sanitizers, it
8479+ still has an impact on the definedness of arithmetic expressions containing
8480+ wrapping components. Since the behavior of said expressions is now technically
8481+ defined, the compiler will forgo some eager optimizations that are used on
8482+ expressions containing UB.
8483+ }];
8484+ }
8485+
0 commit comments