@@ -8446,3 +8446,72 @@ Declares that a function potentially allocates heap memory, and prevents any pot
84468446of ``nonallocating`` by the compiler.
84478447 }];
84488448}
8449+
8450+ def WrapsDocs : Documentation {
8451+ let Category = DocCatField;
8452+ let Content = [{
8453+ This attribute can be used with type or variable declarations to denote that
8454+ arithmetic containing these marked components have defined overflow behavior.
8455+ Specifically, the behavior is defined as being consistent with two's complement
8456+ wrap-around. For the purposes of sanitizers or warnings that concern themselves
8457+ with the definedness of integer arithmetic, they will cease to instrument or
8458+ warn about arithmetic that directly involves a "wrapping" component.
8459+
8460+ For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
8461+ will not warn about suspicious overflowing arithmetic -- assuming correct usage
8462+ of the wraps attribute.
8463+
8464+ This example shows some basic usage of ``__attribute__((wraps))`` on a type
8465+ definition when building with ``-fsanitize=signed-integer-overflow``
8466+
8467+ .. code-block:: c
8468+
8469+ typedef int __attribute__((wraps)) wrapping_int;
8470+
8471+ void foo() {
8472+ wrapping_int a = INT_MAX;
8473+ ++a; // no sanitizer warning
8474+ }
8475+
8476+ int main() { foo(); }
8477+
8478+ In the following example, we use ``__attribute__((wraps))`` on a variable to
8479+ disable overflow instrumentation for arithmetic expressions it appears in. We
8480+ do so with a popular overflow-checking pattern which we might not want to trip
8481+ sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
8482+
8483+ .. code-block:: c
8484+
8485+ void foo(int offset) {
8486+ unsigned int A __attribute__((wraps)) = UINT_MAX;
8487+
8488+ // check for overflow using a common pattern, however we may accidentally
8489+ // perform a real overflow thus triggering sanitizers to step in. Since "A"
8490+ // is "wrapping", we can avoid sanitizer warnings.
8491+ if (A + offset < A) {
8492+ // handle overflow manually
8493+ // ...
8494+ return;
8495+ }
8496+
8497+ // now, handle non-overflow case ...
8498+ }
8499+
8500+ The above example demonstrates some of the power and elegance this attribute
8501+ provides. We can use code patterns we are already familiar with (like ``if (x +
8502+ y < x)``) while gaining control over the overflow behavior on a case-by-case
8503+ basis.
8504+
8505+ When combined with ``-fwrapv``, this attribute can still be applied as normal
8506+ but has no function apart from annotating types and variables for readers. This
8507+ is because ``-fwrapv`` defines all arithmetic as being "wrapping", rendering
8508+ this attribute's efforts redundant.
8509+
8510+ When using this attribute without ``-fwrapv`` and without any sanitizers, it
8511+ still has an impact on the definedness of arithmetic expressions containing
8512+ wrapping components. Since the behavior of said expressions is now technically
8513+ defined, the compiler will forgo some eager optimizations that are used on
8514+ expressions containing UB.
8515+ }];
8516+ }
8517+
0 commit comments